当前文件行号为$。变量

时间:2013-11-16 16:03:15

标签: perl text-files line-numbers

据我所知,我可以使用内置变量$.获取我正在循环的文件的当前行号。作为一项实验,我使用它为文件中的每一行添加前缀$.(当前行号)。但是,这没有按预期工作。即给出以下文件内容

line one
line two
line three

然后我希望以下代码在每行前面添加其行号

for my $line (<FILE>) {
    print "$. : $line";
}

但是,它提供了以下输出

3 line one
3 line two
3 line three

在每行前面加上文件中的行数。而不是当前的线。

1 个答案:

答案 0 :(得分:17)

那是因为你编写循环的方式是在循环遍历行之前读取整个文件。除非您有特殊理由需要比简单顺序访问文件更好的内容,否则应使用while代替for,如下所示:

while (my $line = <FILE>) {
  print "$. : $line";
}

在列表上下文中调用< 文件句柄 >时(就像在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";
}