Most examples of inplace editing are one-liners that iterate through a file or files, reading and printing one line at a time.
I can't find any examples of reading an entire file into an array, modifying the array as needed, and then printing the array while using the ^I switch to do an inplace edit. When I try to read the entire file from the diamond operator, edit the contents and print the entire contents, I find that the print goes to STDOUT instead of ARGVOUT and that ARGVOUT is closed. I can open the same file for output and then print to it, but I'm not sure I understand why that is necessary. Here is an example:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my $filename = 'test.txt';
push @ARGV, $filename;
$^I = ".bk";
my @file = <>; #Read all records into array
chomp @file;
push @file, qw(add a few more lines);
print join "\n", @file; #This prints to STDOUT, and ARGVOUT is closed. Why?
Running the above makes a backup of the test.txt file as expected, but leaves the edited test.txt empty, printing the edited contents to STDOUT instead.
See
perlrun.When the
-iswitch has been invoked, perl starts the program usingARGVOUTas the default file handle instead ofSTDOUT. If there are multiple input files, then every time the<>or<ARGV>orreadline(ARGV)operation finishes with one of the input files, it closesARGVOUTand reopens it to write to the next output file name.Once all the input from
<>is exhausted (when there are no more files to process), perl closesARGVOUTand restoresSTDOUTas the default file handle again. Or asperlrunsaysis equivalent to
Once you say
my @file = <>and consume all the input, Perl closes the filehandle to the backup files and starts directing output toSTDOUTagain.The workaround, I think, is to call
<>in scalar context and checkeof(ARGV)after each line. Wheneof(ARGV)=1, you have read the last line in that file and you get one chance to print before you call<>again: