in reply to Oneliner replace in-place adds extra spaces at the end of the file

What you're seeing is the effect of the -l switch combined with the -0 switch - the order of these two switches matters! Here are some select quotes from perlrun to explain:

-l[octnum]

enables automatic line-ending processing. It has two separate effects. First, it automatically chomps $/ (the input record separator) when used with "-n" or "-p". Second, it assigns $\ (the output record separator) to have the value of octnum so that any print statements will have that separator added back on. If octnum is omitted, sets $\ to the current value of $/. ... Note that the assignment $\ = $/ is done when the switch is processed, so the input record separator can be different than the output record separator if the -l switch is followed by a -0 switch:

gnufind / -print0 | perl -ln0e 'print "found $_" if -p'

This sets $\ to newline and then sets $/ to the null character.

-0[octal/hexadecimal]

specifies the input record separator ($/) as an octal or hexadecimal number. If there are no digits, the null character is the separator. ... The special value 00 will cause Perl to slurp files in paragraph mode. Any value 0400 or above will cause Perl to slurp files whole, but by convention the value 0777 is the one normally used for this purpose.

You can see this effect with B::Deparse:

$ perl -MO=Deparse -0lpe 's/2/4/gs' BEGIN { $/ = "\000"; $\ = "\000"; } ... $ perl -MO=Deparse -l0pe 's/2/4/gs' BEGIN { $/ = "\n"; $\ = "\000"; } ... $ perl -MO=Deparse -lp0e 's/2/4/gs' BEGIN { $/ = "\000"; $\ = "\n"; } ... $ perl -MO=Deparse -l1p0e 's/2/4/gs' BEGIN { $/ = "\000"; $\ = "\001"; } ...

I noticed that over in your last question, hippo suggested the -0 switch, however, note how this sets the record separator(s) to the NUL character, which may not be what you mean (I was even considering nitpicking this when I saw it but the site was really slow again :-( ). Personally, I use the suggested -0777 when I really want slurp mode, and I use it before the -l switch, e.g.:

$ perl -MO=Deparse -0777 -lpe 's/2/4/gs' BEGIN { $/ = undef; $\ = ""; } ...

And if you do that, you'll notice that Perl won't mess with any of the newlines, since it just slurps the entire file into $_ and doesn't add any newlines on output. (Note that if you're on Windows, you may additionally have the :crlf PerlIO layer to contend with depending on which of the variants above you use.)

Update: Updated the example above to show the difference between -l0p (-l with octnum=0) and -lp0 (-l with no octnum plus -0).

Replies are listed 'Best First'.
Re^2: Oneliner replace in-place adds extra spaces at the end of the file
by ikegami (Patriarch) on Oct 27, 2025 at 04:13 UTC

    The solution here isn't to switch the order of -l and -0, but to remove -l entirely.


    I use the suggested -0777 when I really want slurp mode

    For the curious,

    • -0: A line is a sequence of characters terminated by a NUL or EOF.
    • -0777: A line is a sequence of characters terminated by EOF, i.e. the entire file is a line.
    • -g: Same as -0777. (5.36+)
      The solution here isn't to switch the order of -l and -o, but to remove -l entirely.

      Yes, that's a good point, in bliako's example the -l isn't needed, e.g. perl -i -0777pe 's/2/4/gs'.

      In general, one might still want to use -0777 and -l together to change $\. A few more TIMTOWTDI examples doing that:

      $ perl -MO=Deparse -0777l11ne ... BEGIN { $/ = undef; $\ = "\t"; } ... $ perl -MO=Deparse -l11n0777e ... BEGIN { $/ = undef; $\ = "\t"; } ... $ perl -MO=Deparse -ln0777e ... BEGIN { $/ = undef; $\ = "\n"; } ...

      thanks for this. minor neatpick: in the whole thread I see different renderings for the number Zero, compare 0, 0 and 0 and 0, I guess your -o is actually -0? I will use -0777 from now one because my files are not huge and slurping gives me more flexibility. Indeed -l and s///g*s* were from my wider use-case.

        Yeah, one use was accidentally the letter "o". Fixed.

Re^2: Oneliner replace in-place adds extra spaces at the end of the file
by bliako (Abbot) on Oct 27, 2025 at 11:22 UTC

    Great, thanks, also noting comments from ikegami.

    My use-case is part of a bigger setting whereas I find it convenient/simpler/fool-proof to slurp the whole file (tiny file sizes). So, I will not use -l but will use -0777. And I will use -p not because of its loop around the chunks being slurp at the tiem but because of its final print.

      Do note that 0777 does not slurp all input, just until EOF; with multiple input files it loops over them, one chunk per file.

        Oh OK