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



我已经开始玩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输入时,它用新的STIN输入冲击STDIN缓冲器$_并开始打印。

您可以自己使用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

现在,很容易知道第二种情况出了什么问题。外层吃掉了文件的第一行,文件丢失了。

-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 $_
    }
}

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