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$xis 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