在严格模式下将 STDIN 分配给变量

Assign STDIN to variable in strict mode

以下代码在使用 no strict 时完全符合预期:

my $file = STDIN;
while (<$file>) {
    print "$_\n";
}

如何使用 use strict; 得到一个相等的解决方案?


到目前为止我已经尝试过:${STDIN}$STDIN$STDIN<STDIN>\STDIN,我知道最后一个两个运算符(<>\)的含义与我想在这里使用的不同。

STDIN到底是个什么样的变量?它被认为是标量吗?

my $stdin_h = \*STDIN;

提供的惊喜最少。那是一个 globref.

另见 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 是一个裸词。当函数的参数需要文件句柄时,它等效于上述 \*STDIN 之一,但在其余时间等效于 "STDIN"use strict 'refs'; 会引发错误) .

我链接到的 Perl 文档解释了所涉及的各种数据类型之间的差异,但 DavidW 的简短摘要很有用:

*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 you open FH ..., FH is a file handle. When you use open my $fh ..., $fh is a type glob ref.

有一种将文件句柄实际放入变量的方法,在 Perl 文档中有所提及。

然而,它涉及深奥的 Perl 奥秘,这可能会让许多不熟悉这些秘密的开发人员感到困惑。你必须知道查看 perldata and look in the very last section,那就是如果你弄清楚 Typeglob 是什么。

还有一种不那么神秘也更容易理解的方法:

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");
}

好吧,这也不完全 crystal 清楚,但它确实有一个优点,即您知道在哪里可以找到文档。 fileno 是一个函数,因此很容易查找(Returns 文件句柄的文件描述符,如果文件句柄未打开则为未定义。)。

并且由于 fdopenIO::File 的一个方法,您知道您可以在 IO::File Perldoc 中找到相关信息。

好吧,我撒谎了,fdopen 的文档实际上在 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.