Reputation: 4395
I have the following code in a file perl_script.pl
:
while (my $line = <>) {
chomp $line;
// etc.
}.
I call the script with more than 1 file e.g.
perl perl_script.pl file1.txt file2.txt
Is there a way to know if the $line
is started to read from file2.txt
etc?
Upvotes: 5
Views: 537
Reputation: 66873
The $ARGV variable
Contains the name of the current file when reading from
<>
and you can save the name and test on every line to see if it changed, updating when it does.
If it is really just about getting to a specific file, as the question seems to say, then it's easier since you can also use @ARGV
, which contains command-line arguments, to test directly for the needed name.
One other option is to use eof (the form without parenthesis!) to test for end of file so you'll know that the next file is coming in the next iteration -- so you'll need a flag of some sort as well.
A variation on this is to explicitly close the filehandle at the end of each file so that $.
gets reset for each new file, what normally doesn't happen for <>
, and then $. == 1
is the first line of a newly opened file
while (<>) {
if ($. == 1) { say "new file: $ARGV" }
}
continue {
close ARGV if eof;
}
Upvotes: 12
Reputation: 132720
There's the eof
trick, but good luck explaining that to people. I usually find that I want to do something with the old filename too.
Depending on what you want to do, you can track the filename you're working on so you can recognize when you change to a new file. That way you know both names at the same time:
use v5.10;
my %line_count;
my $current_file = $ARGV[0];
while( <> ) {
if( $ARGV ne $current_file ) {
say "Change of file from $current_file to $ARGV";
$current_file = $ARGV;
}
$line_count{$ARGV}++
}
use Data::Dumper;
say Dumper( \%line_count );
Now you see when the file changes, and you can use $ARGV
Change of file from cache-filler.pl to common.pl
Change of file from common.pl to wc.pl
Change of file from wc.pl to wordpress_posts.pl
$VAR1 = {
'cache-filler.pl' => 102,
'common.pl' => 13,
'wordpress_posts.pl' => 214,
'wc.pl' => 15
};
Depending what I'm doing, I might not let the diamond operator do all the work. This give me a lot more control over what's happening and how I can respond to things:
foreach my $arg ( @ARGV ) {
next unless open my $fh, '<', $arg;
while( <$fh> ) {
...
}
}
Upvotes: 3
Reputation: 239652
A useful trick which is documented in perldoc -f eof is the } continue { close ARGV if eof }
idiom on a while (<>)
loop. This causes $.
(input line number) to be reset between files of the ARGV
iteration, meaning that it will always be 1
on the first line of a given file.
Upvotes: 5