Perl在-n命令行选项标志上吃第一行

时间:2015-12-07 13:40:43

标签: perl

我已经开始玩perl了,我试图弄清楚如果我还提供循环,告诉perl使用循环有什么问题?

看起来perl与相同的打开文件描述符混淆了,但我不知道为什么它会吃掉第一行?

perl -ne 'while (<>) { print $_; }'

当然在这个简单的例子中,我可以简单地perl -ne '{print $_}'来达到相同的功能逻辑。

但我想知道的是,如果另一个while (<>) { }被包裹,第一行消失的双循环会出现什么问题?

$ perl -ne '{print $_}' hello
hello
hello
world
world
^C

$ perl -ne 'while (<>) { print $_; }' 
hello
world
world
^C

更新:根据答案,似乎正在发生的事情是Perl正在等待STDIN输入的第一个循环。在STDIN上接收输入后,输入被分配给内部缓冲区$_,逻辑进入第二个循环,再次等待新的STDIN输入。收到新的STDIN输入后,它会使用新的STDIN输入破坏STDIN缓冲区$_并开始打印。

2 个答案:

答案 0 :(得分:9)

您可以使用O=Deparse检查单行生成的代码。

<强>首先

$ perl -MO=Deparse  -ne 'print $_;' file
LINE: while (defined($_ = <ARGV>)) {
    print $_;
}
-e syntax OK

<强>第二

$ perl -MO=Deparse -ne 'while (<>) { print $_; }' file
LINE: while (defined($_ = <ARGV>)) {
    while (defined($_ = <ARGV>)) {
        print $_;
    }
}
-e syntax OK

现在,很容易知道第二种情况有什么问题。外面吃了第一行文件而丢失了。

答案 1 :(得分:3)

-n标志将您的代码包装在while (<>) { ... }构造中。

所以在你的第二个例子中,实际执行的代码是

while (<>) # reads a line from STDIN, places it in $_
{
    # you don't do anything with the contents of $_ here

    while (<>) # reads a line from STDIN, places it in $_, overwriting the previous value
    {
        print $_; # prints the contents of $_
    }
}

这意味着第一个<>读取的行只是丢失了。