I'm using Perl's diamond <>
operator to read from files specified on the command line.
I'd like to be able to report messages like "Trouble on line $. of file $FILENAME"
, but how can I tell which file is currently used by the diamond?
I'm using Perl's diamond <>
operator to read from files specified on the command line.
I'd like to be able to report messages like "Trouble on line $. of file $FILENAME"
, but how can I tell which file is currently used by the diamond?
See perlvar:
$ARGV
Contains the name of the current file when reading from <> .
But also consider $.
in perlvar. If you do this with perl -n
it might not turn out the way you want it, because the counter is not reset in the perl -n
use case.
$.
Current line number for the last filehandle accessed.
Each filehandle in Perl counts the number of lines that have been read from it. (Depending on the value of
$/
, Perl's idea of what constitutes a line may not match yours.) When a line is read from a filehandle (viareadline()
or<>
), or whentell()
orseek()
is called on it,$.
becomes an alias to the line counter for that filehandle.You can adjust the counter by assigning to
$.
, but this will not actually move the seek pointer. Localizing$.
will not localize the filehandle's line count. Instead, it will localize perl's notion of which filehandle$.
is currently aliased to.
$.
is reset when the filehandle is closed, but not when an open filehandle is reopened without an interveningclose()
. For more details, see I/O Operators in perlop. Because<>
never does an explicit close, line numbers increase across ARGV files (but see examples in eof).You can also use
HANDLE->input_line_number(EXPR)
to access the line counter for a given filehandle without having to worry about which handle you last accessed.Mnemonic: many programs use "." to mean the current line number.
Here's an example:
$ perl -nE 'say "$., $ARGV";' foo.pl bar.pl
1, foo.pl
2, foo.pl
3, foo.pl
4, foo.pl
5, foo.pl
6, foo.pl
7, foo.pl
8, foo.pl
9, foo.pl
10, foo.pl
11, foo.pl
12, foo.pl
13, bar.pl
14, bar.pl
15, bar.pl
If you want it to reset, you need to check for eof
at the end of your read loop (thanks @Borodin). Also see the perldoc for eof
:
$ perl -nE 'say "$., $ARGV"; close ARGV if eof' foo.pl bar.pl