在Perl中的输出流:STDERR,STDOUT

4

我知道输出流STDOUT和STDERR。每当你打印到STDOUT时,在Unix shell中,你可以像这样重定向输出...

deviolog@home:~$ perl test_script.pl > output.txt

或者

deviolog@home:~$ perl test_script.pl 1> output.txt

当你打印到 STDERR 时,它看起来相同,但你切换到“通道”编号2:

deviolog@home:~$ perl test_script.pl 2> output.txt

我可以在output.txt中找到我之前作为错误输出打印的内容。

我的问题是,我是否可以以某种方式访问“通道”号码3? 是否有类似于...

 print STDX "Hello World!\n";

...能够实现像下面这样的重定向吗?

deviolog@home:~$ perl test_script.pl 3> output.txt

附言:一个子问题是关于那些“通道”的术语 ^_^


2
“通道号”是“文件描述符”。 - Jonathan Leffler
3个回答

8

您可以使用open命令为已打开的文件描述符(fd)创建一个Perl文件句柄,将&=附加到模式后,使用文件描述符作为文件名。在您的情况下,您需要使用以下命令:

open(my $fh, '>&=', 3)

例如,
$ perl -E'
   open(my $fh, ">&=", 3) or die $!;
   say fileno($fh);
   say $fh "meow";
' 3>output.txt
3

$ cat output.txt
meow

8
你看到我做了什么了吗?我让猫喵喵叫。 :D - ikegami
点赞 +1,为出色的解决方案点赞 - user1121951

1

> file2> file 称为 I/O重定向, 其中2等数字是 文件描述符

在Perl中,STDIN是标准输入,对应于文件描述符1,STDOUTSTDOUT分别对应文件描述符2和3。其他文件描述符没有STDX。但是您可以使用以下方法打开与其他文件描述符相对应的文件句柄(请参见open):

open my $fh, ">&", 3; # $fh will correspond to fd 3, for write

或者

open my $fh, ">&=", 3; # $fh will correspond to fd 3, for write

在运行Perl程序之前,您需要打开文件描述符3(用于写入):
perl script.pl 3> file

之后,例如 print $fh ... 这样的语句生成的输出将出现在 file 中。


1
open my $fh, ">&", 3; 将为文件描述符 4(或任何可用的)创建一个文件句柄,并将其复制为文件描述符 3。 (通过在我的答案中的代码中更改 >&=>&,您可以看到这一点。)这是浪费资源。 - ikegami
@ikegami 是的,>& 会调用 dup,但是 >&= 会调用 fdopen。因此后者更节约文件描述符。除此之外,这两种方法不应该有任何其他区别。 - Lee Duhem
close($fh) 会是一样的吗? - ikegami
@ikegami 噢,那是另一个不同之处。 - Lee Duhem
兄弟,看看“编辑队列”……有些人试图修复:“STDOUT和STDOUT对应于文件描述符2和3”时,它显示“已满”。 - Artfaith

0

不行,因为我所知道的操作系统都没有提供第三个默认句柄给控制台程序。*nix和Windows都提供stdin、stdout和stderr(0、1、2)。这些自动提供给程序,允许它从控制台获取输入并将正常缓冲或异常非缓冲(错误)输出写入。

因此,如其他答案所示,您可以调用open()打开一个句柄并强制将其设置为fd 3,但为什么要麻烦呢?这是非标准的,有点毫无意义,人们会对你产生疑问。

只需使用open()打开要写入的文件即可。


不是我点的踩,但是...你关于默认行为是正确的,但是你可以使用诸如 program 3> another-file 的符号显式地打开一个文件描述符,而不是 {0,1,2}。 - Jonathan Leffler
是的,你可以,但为什么?有什么意义吗?你必须在命令行上做一些特殊的事情,在程序中也要做一些特殊的事情。而且不管谁给我点了踩,请留下评论解释原因。 - Rob K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接