Perl STDOUT是什么类型的,我如何选择写入它?
STDOUT有“类型”吗 产生:Perl STDOUT是什么类型的,我如何选择写入它?,perl,stdout,filehandle,Perl,Stdout,Filehandle,STDOUT有“类型”吗 产生: STDOUT = STDOUT *STDOUT = *main::STDOUT \*STDOUT = GLOB(0x600078848) 我理解*main::STDOUT和GLOB(0x600078848)条目。“空话”让我好奇 我这样问是因为我想把一个类似文件句柄的参数传递给一个方法调用。在“C”中,我将使用文件描述符或文件*。我希望它默认为标准输出。我所做的是: $OUT_FILE_HANDLE = \*STDOUT; if(@ARGV > 0 )
STDOUT = STDOUT
*STDOUT = *main::STDOUT
\*STDOUT = GLOB(0x600078848)
我理解*main::STDOUT
和GLOB(0x600078848)
条目。“空话”让我好奇
我这样问是因为我想把一个类似文件句柄的参数传递给一个方法调用。在“C”中,我将使用文件描述符或文件*。我希望它默认为标准输出。我所做的是:
$OUT_FILE_HANDLE = \*STDOUT;
if(@ARGV > 0 ) {
open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;
}
它起作用了,但我不知道我到底做了什么。我搞砸了吗?我怀疑我已经“破坏”(覆盖)了STDOUT,这不是我想要的
请原谅这个复合问题;他们似乎有关联。来自:
以数字或标点字符开头的Perl标识符不受包
声明的影响,并且总是强制位于包主
中;它们也可以免除严格的“vars”
错误。其他一些名称也可以通过以下方式豁免:[……]STDOUT
因此,STDOUT
是一个包含预打开文件句柄的全局变量
发件人:
如果FILEHANDLE是未定义的标量变量(或数组或哈希元素),则新的FILEHANDLE将自动激活,这意味着该变量将被分配一个对新分配的匿名FILEHANDLE的引用。否则,如果FILEHANDLE是表达式,则其值为真实的FILEHANDLE
您的$OUT\u FILE\u句柄
不是未定义的,因此打开的是它的值STDOUT
。好的,如果你打开一个已经打开的句柄,它首先被隐式关闭
有几种方法可以做你想做的事。从上面的引文中可以明显看出第一点-不要在打开之前定义$OUT\u FILE\u句柄
:
if (@ARGV > 0 ) {
open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;
} else {
$OUT_FILE_HANDLE = \*STDOUT;
}
# do stuff to $OUT_FILE_HANDLE
另一种方法是使用选择
,因此不需要传递文件句柄:
if (@ARGV > 0 ) {
open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;
select $OUT_FILE_HANDLE;
}
# do stuff (without specifying a file handle)
select 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)
这个新的、独立的文件句柄可以重新打开到另一个资源,而不会影响标准输出。看
$OUT\u FILE\u HANDLE=\*STDOUT问题中的code>创建了一个别名,因此当“新”的别名更改时,STDOUT
确实会更改。您可以通过打印
或者从符号表中为这两种类型打印IO
插槽
say for *{$main::NEW}{IO}, *{$main::{STDOUT}}{IO};
并看到(对象字符串化为)相同(例如IO::File=IO(0x1a8ca50)
)
在第一个代码段中(但作为全局our
),使用open
模式&
复制它时,它会打印*main::NEW
,并且它的IO::File
对象与STDOUT
的对象不同。(将其设置为全局我们的
,以便它位于此检查的符号表中,但不用于实际使用;最好有一个词汇表。)您的问题的这一部分没有得到回答:
“空话”让我好奇
没有其他意义的标识符是一个自动生成的字符串文字。[1]例如,foo
与'foo'
相同
$ perl -e'my $x = foo; print "$x\n";'
foo
这很容易出错,所以我们使用使用严格的qw(subs)代码>以防止出现这种情况
$ perl -e'use strict; my $x = foo; print "$x\n";'
Bareword "foo" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.
有关Perl可以指定的其他含义,请参见
select
可能更适合perl/lisp。我还想到了一个动态范围的STDOUT
。这可能就是select的实现方式。谢谢。printf STDERR中的STDOUT
(“STDOUT=%s\n”,STDOUT)
是“诗意优化”兼容性错误特性的一个示例--标准输出
裸字被视为文字字符串,与标准输出
相同。这是使用strict
的一个错误,您应该始终使用它。至于你声称了解typeglobs和handles,这对你来说太棒了!我总是要想一想它们是如何在解释器中实现的,以便理解混乱的情况。我认为它有时被解释为一个子?我不知道,因为我总是使用严格的。在这个例子中,我必须把它取出来,看看会发生什么。如果以前声明过一个同名的sub,它就会被解释为sub调用。这是我提到的“其他含义”之一。我还有一个问题,但我不知道如何表达它。有没有一种编程方式可以查看/知道编译器将如何解释一个裸字?在上面的程序中,我试着打印标准输出,结果是8,而不是7。我想。您可以使用-MO=concrete
或-MO=concrete,-exec
查看程序是如何编译的。//该列表是为此答案创建的原始内容。可能会有错误,但由于广泛的测试,我非常自信。(如果有人认为Perl对标识符的解释与此图表不同,我非常希望听到这方面的消息,以便修复此图表)。///如果您指的是printf STDERR(“STDOUT=%s\n”,STDOUT)
,printf
:#5,STDERR
:#7,STDOUT
:#8 4的两个示例完全不同,其中只有一个将覆盖5。比较perl-le'使用常量长度=>7;使用perl-le'BEGIN{package P;*{main::length}=sub(){17}}}print length'
(无法覆盖length
)打印长度“
(手工导出器,覆盖length
,常量折叠就像使用常量
)。
$ perl -e'my $x = foo; print "$x\n";'
foo
$ perl -e'use strict; my $x = foo; print "$x\n";'
Bareword "foo" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.