这是因为您编写的循环方式在循环行之前读取整个文件。除非您有特殊原因需要比简单的顺序访问文件更好的功能,否则应该使用while
而不是for
,就像这样:
while (my $line = <FILE>) {
print "$. : $line";
}
当在列表上下文中调用<
filehandle>
(就像在您的for
循环中一样)时,它将文件的全部内容作为行列表返回。 因此,您的代码的行为方式基本上与您编写以下内容相同:
my @lines = <FILE>; # now $. is set to the end of the file
for my $line (@lines) { ... } # you're just looping over an array, not touching $.
为了达到你想要的结果,你应该在标量上下文中反复调用 <>
(在 while
条件中进行赋值),以从文件中逐行获取并执行循环体,并将 $.
设置为正确的行数。
此外,全局文件句柄被认为是不良实践。出于多种原因,最好使用由词法变量引用的文件句柄,像这样:
open my $file, '<', $filename or die $!;
while (my $line = <$file>) {
print "$. : $line";
}
还有,由于$.
是一个包含最近执行的读操作的行号的全局变量,如果在<$file>
和print
之间有可能出现另一次读取,请不要依赖它。相反,询问正在使用的文件句柄的行号:
open my $file, '<', $filename or die $!;
while (my $line = <$file>) {
print $file->input_line_number, " : $line";
}
即使使用全局文件句柄,这也可以正常工作,尽管有些笨拙:
while (my $line = <FILE>) {
print ${\*FILE}->input_line_number, " : $line";
}
即使是被空的<>
读取的默认值,也被真正命名为ARGV
:
while (my $line = <>) {
print ${\*ARGV}->input_line_number, " : $line";
}