为什么在perl one liner中使用-p | -n的slurp模式?

时间:2016-06-02 04:08:27

标签: perl

在perl中,一个衬里啜食模式是open my $fh, "<","file"; local $/; my $s = <$fh>; #now whole file stored into the $s 我希望哪个等于下面的脚本

-p|-n

这里我们没有使用任何循环将所有元素存储在一起(单个数据)。

但是在perl one liner中,为什么我们使用-0777开关来启用slurp模式(-p | -n)?这里的性能提升是多少?

open my $fh, "<","file"; my $s; while (<$fh>) { $s.=$_; } print $s; 用于循环目的。那么一个班轮的实际表现就像下面的剧本或其他什么?

EditText

3 个答案:

答案 0 :(得分:5)

如果没有-n-p,则没有隐式while (<>)循环,因此默认$_未设置,并且STDIN也未读取。如果我们希望在slurp模式下默认<>$_,我们需要其中一个开关以及-0777,它本身只是(联合国)设置$/ 。此

echo "hello" | perl -0777 -e 'print'

不打印任何内容,-w警告Use of uninitialized value $_。现在这个

echo "hello" | perl -0777 -e '$v = <>; print $v'

会打印helloSTDIN可以读入一个变量,因此&#39; slurp&#39;

就这相当于什么而言,仅仅-0777只有$/ = undef。如果我们添加一个读取

# use warnings;
local $/;
<>; 
print;

<>一次性读取所有内容,但没有默认输入和模式搜索空间 $_,因此读取的内容不会分配给任何内容。随着警告我们得到了解。 (感谢Jonathan Leffler在评论中提到STDIN。)相当于使用-n的代码是

while (defined($_ = <ARGV>)) { }

因此我们获得标准输入并设置$_。运行perl -MO=Deparse -n -e 1即可查看这些内容。

perlvar中列出的条件为&#34; ... Perl将假设$_ ... &#34;。最后一颗子弹

  

<FH>readlinereaddireach操作的结果自行测试时,放置下一个值或输入记录的默认位置while测试的唯一标准。在while测试之外,这不会发生。

使用-n-p开关,我们可以获得此标准输入。

注意,您的示例并非完全等效,因为它 分配。

评论问题中的具体陈述。

啜食没有&#34; 启用&#34;通过这些开关 - 它由-0777标志设置。我们使用它们是因为我们获得了自动标准输入和$_

答案 1 :(得分:2)

这更像是运行perl -n0e '$s = $_'

% perl -MO=Deparse -n0e '$s = $_'
BEGIN { $/ = "\000"; $\ = undef; }                                                                                                                                                                                                
LINE: while (defined($_ = <ARGV>)) {                                                                                                                                                                                              
    $s = $_;                                                                                                                                                                                                                      
}                                                                                                                                                                                                                                 
-e syntax OK

正如您所看到的那样,唯一的“开销”是一次性检查。毕竟$/是一个NUL字节。正如其他人所指出的,这是完成工作的一种简单方法:

考虑这个简单的sed等于:

perl -i -pe 's/a/b/g' file1 file2 file3

以上内容将替换file1,file2&amp;中a的所有b。文件3。 Deparsed:

BEGIN { $^I = ""; }                                                                                                                                                                                                               
LINE: while (defined($_ = <ARGV>)) {                                                                                                                                                                                              
    s/a/b/g;                                                                                                                                                                                                                      
}                                                                                                                                                                                                                                 
continue {                                                                                                                                                                                                                        
    die "-p destination: $!\n" unless print $_;                                                                                                                                                                                   
}                                                                                                                                                                                                                                 
-e syntax OK 

答案 2 :(得分:1)

有两个原因;首先,要在一行中完成的工作。单行的整个想法是避免实际编写脚本文件。你的邋alternative替代品不能合理地表达出来。

其次,-n和-p允许对每一行采取行动 - 这与简单地读取所有行不同。使用你的单一替代品读取行后,可以使用map来处理每一行 - 但是我们回到多行代码而不是命令行开关。