The following code works quite as intended when using no strict
:
my $file = STDIN;
while (<$file>) {
print "$_\n";
}
How would be an equal solution using use strict;
?
I've tried so far: ${STDIN}
, $STDIN
, \$STDIN
, <STDIN>
, and \STDIN
, and I am aware that the last two operators (<>
and \
) have different meanings than I want to use here.
What kind of variable is STDIN
anyway? Is it considered a scalar?
my $stdin_h = \*STDIN;
provides the fewest surprises. That is a globref.
See also perldoc perlref and Typeglobs and Filehandles in perldata:
Another use for typeglobs is to pass filehandles into a function or to create new filehandles. If you need to use a typeglob to save away a filehandle, do it this way:
$fh = *STDOUT;
or perhaps as a real reference, like this:
$fh = \*STDOUT;
STDIN
is a bareword. When the argument to a function expecting a file handle, it's equivalent to one of the above \*STDIN
, but it's equivalent to "STDIN"
the rest of the time (for which use strict 'refs';
throws an error).
Perl documentation I linked to explains the differences between the various data types involved, but DavidW's brief summary is useful:
*STDIN
is a type glob. This has to do with how Perl stores info in its symbol table. Perl creates an entry in it's symbol table for a particular name, and then creates hash entries for subroutines, file handles, hashes, arrays, and scalars with those names. You can reference this symbol table entry with a*
sigil and it's called a type glob. The problem is that there is no sigil for file handles, so you have to refer to them with the type glob. When youopen FH ...
,FH
is a file handle. When you useopen my $fh ...
,$fh
is a type glob ref.
Sinan Ünür has a way of actually getting the file handle into a variable and is mentioned in the Perl documentation.
However, it involves deep dark Perl mysteries which may be confusing for many developers who aren't familiar with these secrets. You have to know to look in perldata and look in the very last section, and that's if you figure out what Typeglobs are.
There is another way that's less mysterious and easier to understand:
use strict;
use warnings;
use feature qw(say);
use autodie; # Doesn't work. You need to verify
use IO::File;
...
my $file = IO::File->new;
$file->fdopen( fileno( STDIN ), 'r')
or die qq(<STDIN> is not opened.);
while ( my $entry = <$file> ) {
chomp $entry;
say qw(The entry is "$entry");
}
Okay, this isn't exactly crystal clear either, but it does have an advantage that you know where to look for the documentation. fileno
is a function, so that's easy to look up (Returns the file descriptor for a filehandle, or undefined if the filehandle is not open.).
And since fdopen
is a method of IO::File, you know you can find information about that in the IO::File
Perldoc.
Okay, I lied, the documentation for fdopen
is actually in the IO::Handle Perldoc. But, the IO::File
Perldoc does say that it inherits its methods from IO::Handle
. Once you do figure out to look in IO::Handle
, you see an example of this very code right in the synopsis.
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