in reply to perl -i -pe ... with eof() testing

eof (any form) performs a read if there's nothing in the handle's buffer. If you're at the end of the last file in @ARGV during a read of ARGV, ARGV moves on to the next file. The file to which you want to add is now closed.

Based on black box testing, reading from ARGV (include when done via eof()) under -i is pretty close to

#XXX Doesn't handle empty @ARGV sub fill_argv { if (!eof(ARGV)) { return 1; } while (@ARGV) { $ARGV = shift(@ARGV); if (!open(ARGV, '<', $ARGV)) { warn("Can't open $ARGV: $!"); next; } if (!unlink($ARGV)) { warn("Can't remove $ARGV: $!, skipping file.\n"); next; } if (!open(ARGVOUT, '>', $ARGV)) { warn(???); next; } select(ARGVOUT); return 1; } $ARGV = undef; close(ARGVOUT); select(STDOUT); return 1; }

OT trivia: Note how it always returns success since it always handles errors itself.

Update: Added expansion of reading from ARGV under -i. And then did some tweaks.

Replies are listed 'Best First'.
Re^2: perl -i -pe ... with eof() testing
by Anonyrnous Monk (Hermit) on Feb 08, 2011 at 19:57 UTC

    This is what I figured, too (kind of). But why does it then "work" with the eof form?  This produces

    --- cat before --- line1 line2 line3 line1 line2 line3 --- script output to stdout --- --- cat after --- line1 line2 line3 opt=bar line1 line2 line3 opt=bar

    (I say "work" in quotes because it's not what is needed here, but what I would've expected.)

    Also, perl -MO=Deparse ... doesn't highlight any difference, except the eof vs. eof() itself.

      The only way (eof) can check for per-file eof as documented would be if it read from the real file handle instead of the magical handle. The magical handle doesn't move to the next file because it's not used.

        Thanks, you're right.

        Just for the record: I had confused myself unnecessarily by not putting a separator in between the cat of file1 and file2. Which made me wonder why the magical file handle is only being advanced by eof() at the very end, and not at every file boundary.  When you do it properly, however, i.e. something like

        cat file1 echo --- cat file2

        the output is

        ... --- perl output to stdout --- line3 opt=bar --- cat after --- line1 line2 --- line3 line1 line2

        which shows that line3 of the first file does in fact belong to file2 after the processing...

        P.S. I've now settled on suggesting my collegue

        perl -i -pe '$f||=s/opt=.*/opt=bar/; $_.="opt=bar\n" if !$f && !@ARGV +&& eof' files...

        (but unfortunately it took a little too long to get working to leave an "it's easy with Perl" impression — that's my fault, however :)