perl – 读取整个文件,然后在内部编辑时打印?

前端之家收集整理的这篇文章主要介绍了perl – 读取整个文件,然后在内部编辑时打印?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
大多数就地编辑的例子都是单行,它们遍历一个或多个文件,一次读取和打印一行.

我找不到任何将整个文件读入数组,根据需要修改数组,然后在使用^ 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?

运行上述操作会按预期备份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/;

相当于

#!/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);

一旦你说我的@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 = ();
    }
}

猜你在找的Perl相关文章