STDOUT是什么类型,如何选择写入?

Eri*_*ett 4 perl stdout filehandle

STDOUT是否有“类型”?

printf STDERR ("STDOUT = %s\n", STDOUT);
printf STDERR ("\*STDOUT = %s\n", *STDOUT);
printf STDERR ("\\\*STDOUT = %s\n", \*STDOUT);
Run Code Online (Sandbox Code Playgroud)

产生:

STDOUT = STDOUT
*STDOUT = *main::STDOUT
\*STDOUT = GLOB(0x600078848)
Run Code Online (Sandbox Code Playgroud)

我了解*main::STDOUTGLOB(0x600078848)条目。这个“流行语”让我感到好奇。

我问是因为我想将类似文件句柄的参数传递给方法调用。在“ C”中,我将使用文件描述符或File *。我希望它默认为STDOUT。我所做的是:

$OUT_FILE_HANDLE = \*STDOUT;
if(@ARGV > 0 ) {
    open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;
}
Run Code Online (Sandbox Code Playgroud)

它可以工作,但是我不知道我到底做了什么。我提升了STDOUT吗?我怀疑我已经“毁了”(覆盖)STDOUT,这不是我想要的。

请原谅复合问题;他们似乎有关。

zdi*_*dim 5

创建一个词法文件句柄作为其副本 STDOUT

sub manip_fh { 
    my ($fh) = @_;
    say $fh "hi";                              # goes to STDOUT
    open my $fh, '>', 'a_file.txt' or die $!;  # now it's to a file
    say $fh "hello";
}

open my $fh, '>&', STDOUT;  # via dup2

manip_fh($fh);

say "hi";  # still goes where STDOUT went before being dup-ed (terminal)
Run Code Online (Sandbox Code Playgroud)

然后可以将此新的独立文件句柄重新打开到另一个资源,而不会影响STDOUT。见打开

$OUT_FILE_HANDLE = \*STDOUT;问题中的from会创建一个别名,因此STDOUT当“新”更改时,确实会更改。您可以通过打印typeglob看到

our $NEW = \*STDOUT;
say *{$main::NEW};    #--> *main::STDOUT
Run Code Online (Sandbox Code Playgroud)

或通过打印IO符号表中的插槽

say for *{$main::NEW}{IO}, *{$main::{STDOUT}}{IO};
Run Code Online (Sandbox Code Playgroud)

并看到相同的对象(例如IO::File=IO(0x1a8ca50))。

当像第一个代码片段(但作为全局代码)那样使用openwith模式对它进行复制时,它会打印,并且它的对象与for不同。(将其设为全局,以便仅在此表中用于此检查,而不是在实际中使用;拥有词法更好。)>&our*main::NEWIO::FileSTDOUTour


Ama*_*dan 4

来自珀尔瓦尔

\n\n
\n

以数字或标点符号开头的 Perl 标识符不受package声明的影响,并且始终强制位于包中main;它们也不会出现strict \'vars\'错误。其他一些名称也可以通过以下方式豁免:[...]STDOUT

\n
\n\n

因此,STDOUT是一个包含预先打开的文件句柄的全局变量。

\n\n

来自perlfunc

\n\n
\n

如果 FILEHANDLE 是未定义的标量变量(或数组或散列元素),则新文件句柄将自动生成,这意味着该变量被分配对新分配的匿名文件句柄的引用。否则,如果 FILEHANDLE 是一个表达式,则其值是真正的文件句柄。

\n
\n\n

Your$OUT_FILE_HANDLE不是未定义的,因此STDOUT正在打开的是它的值 。AFAIK,如果您打开一个已经打开的句柄,它会首先隐式关闭。

\n\n

有几种方法可以做你想做的事。$OUT_FILE_HANDLE从上面的引用 \xe2\x80\x94 中可以明显看出,在 之前不要定义open

\n\n
if (@ARGV > 0 ) {\n  open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;\n} else {\n  $OUT_FILE_HANDLE = \\*STDOUT;\n}\n# do stuff to $OUT_FILE_HANDLE\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一种是使用select,因此您不需要传递文件句柄:

\n\n
if (@ARGV > 0 ) {\n  open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;\n  select $OUT_FILE_HANDLE;\n}\n# do stuff (without specifying a file handle)\nselect STDOUT;\n
Run Code Online (Sandbox Code Playgroud)\n