Code
$ cat test1
hello
i am
lazer
nananana
$ cat 1.pl
use strict;
use warnings;
my @fh;
open $fh[0], '<', 'test1', or die $!;
my @res1 = <$fh[0]>; # Way1: why does this not work as expected?
print @res1."\n";
my $fh2 = $fh[0];
my @res2 = <$fh2>; # Way2: this works!
print @res2."\n";
Run
$ perl 1.pl
1
5
$
I am not sure why Way1
does not work as expected while Way2
does. Aren't those two methods the same? What is happening here?
Because of the dual nature of the <> operator (i.e. is it glob or readline?), the rules are that to behave as readline, you can only have a bareword or a simple scalar inside the brackets. So you'll have to either assign the array element to a simple scalar (as in your example), or use the readline function directly.
Because from perlop:
If what's within the angle brackets is neither a filehandle nor a simple scalar variable containing a filehandle name, typeglob, or typeglob reference, it is interpreted as a filename pattern to be globbed, and either a list of filenames or the next filename in the list is returned, depending on context. This distinction is determined on syntactic grounds alone. That means <$x>
is always a readline() from an indirect handle, but <$hash{key}>
is always a glob().
You can spell the <>
operator as readline instead to avoid problems with this magic.
Anything more complex than a bareword (interpreted as a file handle) or a simple scalar $var
is interpreted as an argument to the glob()
function. Only barewords and simple scalars are treated as file handles to be iterated by the <...>
operator.
Basically the rules are:
<bareword> ~~ readline bareword
<$scalar> ~~ readline $scalar
<$array[0]> ~~ glob "$array[0]"
<anything else> ~~ glob ...
It's because <$fh[0]>
is parsed as glob($fh[0])
.
Use readline
instead:
my @res1 = readline($fh[0]);