2

我有一个简单的问题:

为什么第一个代码不打印文件的第一行但第二个代码呢?

#! /usr/bin/perl

use warnings;
use strict;

my $protfile = "file.txt";
open (FH, $protfile);
while (<FH>) {
         print (<FH>);

}

#! /usr/bin/perl

use warnings;
use strict;

my $protfile = "file.txt";
open (FH, $protfile);
while (my $file = <FH>) {
         print ("$file");

}
4

4 回答 4

5

语境。

您的第一个程序FH通过读取第一行来测试文件结束,然后FH在列表上下文中读取作为print. 这将转换为整个文件,作为每个项目一行的列表。然后它再次测试 EOF,很可能检测到它,然后停止。

您的第二个程序逐行迭代,每一个都在标量上下文中读取到 variable $file,并单独打印它们。while它通过语法中的特殊情况检测 EOF 。(请参阅文档中的代码示例)

因此,您的程序在一种情况下不打印第一行的具体原因是它在while. 请注意,这两个程序的结构非常不同:第一个只运行一次while迭代,而第二个每行迭代一次。

PS:现在,推荐的文件管理方式倾向于词法文件句柄(open my $file, 'name'; print <$file>;)。

于 2013-09-10T17:50:10.077 回答
3

因为您正在使用 <> 运算符处理第一行,然后在打印中再次使用它,所以第一行已经消失但您没有打印它。<> 是 readline 运算符。您需要打印 $_ 变量,或将其分配给定义的变量,就像您在第二个代码中所做的那样。你可以重写第一个:

打印;

它会起作用,因为如果你不给它任何东西, print 就会使用 $_ 。

于 2013-09-10T17:48:21.143 回答
2

标量上下文中使用时,<FH>返回文件中的下一行。

list context 中使用时,<FH>返回文件中所有剩余行的列表。

while (my $file = <FH>)是标量上下文,因为您要分配给标量。 while (<FH>)是 的缩写while(defined($_ = <FH>)),所以它也是一个标量上下文。 print (<FH>);使它成为一个列表上下文,因为您将它用作可以接受多个参数的函数的参数。

while (<FH>) {
    print (<FH>);
}

while部分将第一行读入$_(不再使用)。然后该print部分一次读取其余的行,然后再次将它们全部打印出来。然后while再次检查条件,但由于现在没有剩余行,因此仅在一次迭代后<FH>返回undef并退出循环。

while (my $file = <FH>) {
    print ("$file");
}

做更多你可能期望的事情:在循环的每次迭代中读取并打印一行。

顺便说一句,print $file;print ("$file");

于 2013-09-10T17:58:46.280 回答
1
while (<FH>) {
    print (<FH>);
}

改用这个:

while (<FH>) {
    print $_;
}
于 2013-09-12T08:03:12.073 回答