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
-i
switch has been invoked, perl starts the program usingARGVOUT
as 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 closesARGVOUT
and 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 closesARGVOUT
and restoresSTDOUT
as the default file handle again. Or asperlrun
saysis equivalent to
Once you say
my @file = <>
and consume all the input, Perl closes the filehandle to the backup files and starts directing output toSTDOUT
again.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: