问题
I understand that I can get the current line number of a file I am looping through with the builtin variable $.
. As an experiment, I used that to prefix each line in a file with the value of $.
(the current line number). However, this did not work as expected. I.e. given the following file contents
line one
line two
line three
then I would expect the following code to prefix each line with its line number
for my $line (<FILE>) {
print "$. : $line";
}
but, instead, it gives the following output
3 line one
3 line two
3 line three
prefixing each line with the number of lines in the file. Instead of the current line.
回答1:
That's because the way you wrote the loop reads the entire file before looping over the lines. Unless you have a special reason to need something better than simple sequential access to the file, you should use while
instead of for
, like this:
while (my $line = <FILE>) {
print "$. : $line";
}
When <
filehandle >
is called in list context (as it is in your for
loop), it returns the entire contents of the file as a list of lines. Therefore, your code behaves in much the same way as if you had written this instead:
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 $.
To achieve your desired result, you should call <>
repeatedly in scalar context (which the assignment in the while
condition does), to fetch one line at a time from the file and execute the body of the loop with $.
set to the correct number.
Also, global filehandles are considered to be bad practice. For several reasons, it's better to use a filehandle referenced by a lexical variable instead, like this:
open my $file, '<', $filename or die $!;
while (my $line = <$file>) {
print "$. : $line";
}
Also, since $.
is a global variable containing the line number from the most recently executed read operation, you shouldn't rely on it if there's any chance of another read occurring between the <$file>
and the print
. Instead, ask the filehandle you're using for its line number:
open my $file, '<', $filename or die $!;
while (my $line = <$file>) {
print $file->input_line_number, " : $line";
}
Which even works, if somewhat more awkwardly, with a global filehandle:
while (my $line = <FILE>) {
print ${\*FILE}->input_line_number, " : $line";
}
... even the default one read by an empty <>
, which is really named ARGV
:
while (my $line = <>) {
print ${\*ARGV}->input_line_number, " : $line";
}
来源:https://stackoverflow.com/questions/20020539/current-file-line-number-with-variable