我正在逐行读取文件,并希望通过子程序处理每一行。由于我对行本身不感兴趣,因此我将文件句柄中的读取直接放入子例程调用中。然而,这导致了我不太了解的意外行为。
我创建了一个演示效果的最小例子:
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );
print "This works as expected:\n";
open my $TEST1, '<', 'filetest1.txt' or croak "Can't open filetest1.txt - $ERRNO";
my $line1 = <$TEST1>;
print_line( $line1 );
while ( 1 ) {
last if eof $TEST1;
$line1 = <$TEST1>;
print $line1;
}
close $TEST1;
print "\n";
print "Unexpected effect here:\n";
open my $TEST2, '<', 'filetest1.txt' or croak "Can't open filetest1.txt - $ERRNO";
print_line(<$TEST2>); # this works, but just once
while ( 1 ) {
last if eof $TEST2; # is triggered immediately
print "This is never printed\n";
print_line(<$TEST2>);
}
close $TEST2;
sub print_line {
my $line = shift;
print $line;
return 1;
}
filetest1.txt的内容:
test line 1
test line 2
test line 3
test line 4
test line 5
脚本结果:
This works as expected:
test line 1
test line 2
test line 3
test line 4
test line 5
Unexpected effect here:
test line 1
似乎当我在子程序调用中直接读取下一行时,它只运行一次然后触发eof。我没有找到任何关于该效果的解释,它迫使我创建变量$ line1只是为了将该行传递给子例程。
我正在寻找解释为什么会发生这种情况的原因,因此我想了解我对文件句柄能做什么或不能做什么的限制。
答案 0 :(得分:3)
在您的代码print_line(<$FH>);
中,文件句柄的读取将以wantarray模式完成,这意味着您不会读取整行文件的单行。在您的子程序中,您只需使用第一行并丢弃其余部分。这就是为什么在第一次循环遇到后文件句柄是空的。
您可以将文件句柄提供给子例程并在那里读取一行:
open my $FH , '<' , 'somefile' or die "Cannot read: $!" ;
while( ! eof $FH ) {
print_line( $FH ) ;
}
sub print_line {
my ( $fh ) = @_ ;
my $line = <$fh> ;
print $line ;
}
答案 1 :(得分:1)
您遇到了上下文问题。 $TEST1
读取位于标量上下文中,因此它只读取一行。 $TEST2
读取位于列表上下文中,因此将读取文件中的所有行,并调用print_line()
并将其列表作为其参数。因此,当您第二次尝试从$TEST2
读取时,您会获得EOF,因为所有行都是第一次读取。