This script:
#!/usr/bin/perl
use strict;
use warnings;
my ${fh};
open($fh, '<', "some_file.txt") or die "fail\n";
while(my $line = <${fh}> ) {
print $line;
}
close $fh;
outputs:
GLOB(0x5bcc2a0)
Why is this the output?
If I change <${fh}>
to <$fh>
, it will print some_file.txt
line by line as expected. I thought the braces could be used to delimit variable names, and that my ${var}
would be the same as my $var
.
Are there other scenarios where adding {}
around a variable name causes problems?
I tried on Perl 5.8.8 on Red Hat and Cygwin Perl 5.14.
From the section on <>
in perlop:
If what the angle brackets contain is a simple scalar variable (for example,
$foo
), then that variable contains the name of the filehandle to input from, or its typeglob, or a reference to the same. For example:$fh = \*STDIN; $line = <$fh>;
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 areadline()
from an indirect handle, but<$hash{key}>
is always aglob()
. That's because$x
is a simple scalar variable, but$hash{key}
is not--it's a hash element. Even<$x >
(note the extra space) is treated asglob("$x ")
, notreadline($x)
.
You can see this with B::Concise:
$ perl -MO=Concise -e'<$fh>'
5 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
4 <1> readline[t1] vK*/1 ->5
- <1> ex-rv2sv sK/1 ->4
3 <$> gvsv(*fh) s ->4
-e syntax OK
$ perl -MO=Concise -e'<${fh}>'
6 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 70 -e:1) v:{ ->3
5 <@> glob[t1] vK/1 ->6
- <0> ex-pushmark s ->3
- <1> ex-rv2sv sK/1 ->4
3 <$> gvsv(*fh) s ->4
4 <$> gv(*_GEN_0) s ->5
-e syntax OK
<>
means readline(ARGV)
<IDENTIFIER>
means readline(IDENTIFIER)
<$IDENTIFIER>
means readline($IDENTIFIER)
<...>
(anything else) means glob(qq<...>)
So,
<$fh>
means readline($fh)
<${fh}>
means glob(qq<${fh}>)
, which is the same as glob("$fh")
.glob
is used to generate a number of strings or file names from a pattern.
In this case, the stringification of the file handle is GLOB(0x5bcc2a0)
. This is being passed to glob, but none of those characters have a special meaning for glob
, so glob
simply returns that string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With