Reputation: 362
I am reading a file line by line and want to process each line through a subroutine. Since I am not interested in the line itself, I put the read from the filehandle directly into the subroutine call. However, this leads to unexpected behaviour I don't quite understand.
I created a minimal example demonstrating the effect:
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );
print "This works as expected:\n";
open my $TEST1, '<', 'filetest1.txt' or croak "Can't open filetest1.txt - $ERRNO";
my $line1 = <$TEST1>;
print_line( $line1 );
while ( 1 ) {
last if eof $TEST1;
$line1 = <$TEST1>;
print $line1;
}
close $TEST1;
print "\n";
print "Unexpected effect here:\n";
open my $TEST2, '<', 'filetest1.txt' or croak "Can't open filetest1.txt - $ERRNO";
print_line(<$TEST2>); # this works, but just once
while ( 1 ) {
last if eof $TEST2; # is triggered immediately
print "This is never printed\n";
print_line(<$TEST2>);
}
close $TEST2;
sub print_line {
my $line = shift;
print $line;
return 1;
}
Content of filetest1.txt:
test line 1
test line 2
test line 3
test line 4
test line 5
Result of the script:
This works as expected:
test line 1
test line 2
test line 3
test line 4
test line 5
Unexpected effect here:
test line 1
It seems that when I read the next line directly in the subroutine call, it works exactly once and then eof is triggered. I haven't found any explanation for that effect, and it forces me to create the variable $line1 just to pass the line to the subroutine.
I'm looking for an explanation why that happens, and consequently I'd like to understand the limits of what I can or cannot do with a filehandle.
Upvotes: 3
Views: 62
Reputation: 13646
In your code print_line(<$FH>);
the reading from the filehandle will be will be done in wantarray-mode meaning you don't read a single line but the whole file. And in your subroutine you just use the first line and discard the rest. Thats why the filehandle is empty after your first loop encounter.
You could just provide the filehandle to the subroutine and read a line there:
open my $FH , '<' , 'somefile' or die "Cannot read: $!" ;
while( ! eof $FH ) {
print_line( $FH ) ;
}
sub print_line {
my ( $fh ) = @_ ;
my $line = <$fh> ;
print $line ;
}
Upvotes: 3
Reputation:
You have a context problem. The $TEST1
read is in scalar context, so it only read one line. The $TEST2
read is in list context, so all the lines from the file are read and print_line()
is called with a list of them as its arguments. So the second time you try to read from $TEST2
you get EOF, since all the lines were read the first time.
Upvotes: 1