d5e*_*5e5 4 perl inplace-editing
大多数就地编辑的例子都是单行,它们遍历一个或多个文件,一次读取和打印一行.
我找不到任何将整个文件读入数组,根据需要修改数组,然后在使用^ I开关进行就地编辑时打印数组的示例.当我尝试从钻石操作员读取整个文件,编辑内容并打印整个内容时,我发现打印转到STDOUT而不是ARGVOUT并且ARGVOUT已关闭.我可以打开相同的文件输出然后打印到它,但我不确定我理解为什么这是必要的.这是一个例子:
#!/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?
Run Code Online (Sandbox Code Playgroud)
运行上述操作会按预期方式备份test.txt文件,但将编辑后的test.txt保留为空,将编辑后的内容打印到STDOUT.
见perlrun.
当-i调用该开关时,perl使用ARGVOUT默认文件句柄而不是启动程序STDOUT.如果有多个输入文件,则每次<>或<ARGV>或readline(ARGV)操作完成一个输入文件时,它会关闭ARGVOUT并重新打开它以写入下一个输出文件名.
一旦所有输入<>都耗尽(当没有更多文件要处理时),perl将关闭ARGVOUT并STDOUT再次恢复为默认文件句柄.或者如perlrun说
#!/usr/bin/perl -pi.orig
s/foo/bar/;
Run Code Online (Sandbox Code Playgroud)
相当于
#!/usr/bin/perl
$extension = '.orig';
LINE: while (<>) {
if ($ARGV ne $oldargv) {
if ($extension !~ /\*/) {
$backup = $ARGV . $extension;
}
else {
($backup = $extension) =~ s/\*/$ARGV/g;
}
rename($ARGV, $backup);
open(ARGVOUT, ">$ARGV");
select(ARGVOUT);
$oldargv = $ARGV;
}
s/foo/bar/;
}
continue {
print; # this prints to original filename
}
select(STDOUT);
Run Code Online (Sandbox Code Playgroud)
一旦你说出my @file = <>并消耗了所有输入,Perl就会将文件句柄关闭到备份文件并开始STDOUT再次指向输出.
我认为,解决方法是调用<>标量上下文并eof(ARGV)在每行后检查.何时eof(ARGV)=1,您已经阅读了该文件中的最后一行,并且在<>再次拨打电话之前有一次机会打印:
my @file = ();
while (<>) {
push @file, $_;
if (eof(ARGV)) {
# done reading current file
@processed_file = &do_something_with(@file);
# last chance to print before ARGVOUT gets reset
print @processed_file;
@file = ();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1132 次 |
| 最近记录: |