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::STDOUT和GLOB(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,这不是我想要的。
请原谅复合问题;他们似乎有关。
创建一个词法文件句柄作为其副本 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
来自珀尔瓦尔:
\n\n\n\n\n以数字或标点符号开头的 Perl 标识符不受
\npackage声明的影响,并且始终强制位于包中main;它们也不会出现strict \'vars\'错误。其他一些名称也可以通过以下方式豁免:[...]STDOUT
因此,STDOUT是一个包含预先打开的文件句柄的全局变量。
来自perlfunc:
\n\n\n\n\n如果 FILEHANDLE 是未定义的标量变量(或数组或散列元素),则新文件句柄将自动生成,这意味着该变量被分配对新分配的匿名文件句柄的引用。否则,如果 FILEHANDLE 是一个表达式,则其值是真正的文件句柄。
\n
Your$OUT_FILE_HANDLE不是未定义的,因此STDOUT正在打开的是它的值 。AFAIK,如果您打开一个已经打开的句柄,它会首先隐式关闭。
有几种方法可以做你想做的事。$OUT_FILE_HANDLE从上面的引用 \xe2\x80\x94 中可以明显看出,在 之前不要定义open:
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\nRun Code Online (Sandbox Code Playgroud)\n\n另一种是使用select,因此您不需要传递文件句柄:
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;\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |