Jim
Jim

Reputation: 4395

How can I know if diamond operator moved to the next file?

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

Answers (3)

zdim
zdim

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

brian d foy
brian d foy

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

hobbs
hobbs

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

Related Questions