![](/img/trans.png)
[英]Perl STDOUT redirected to a pipe, no output after calling sleep()
[英]STDOUT redirected to variable not catching pipe output
我想暂时将stdout重定向到内存变量。 打印正确地重定向到我的变量但不是管道的输出(在我的示例中为bc)。 到底是怎么回事?
#!/usr/bin/perl
my $stdout_sink;
open(my $orig_stdout, ">&STDOUT") || die $!;
close STDOUT;
open(STDOUT, ">", \$stdout_sink) || die $!;
# produce some output in different ways
print "before bc\n"; # ok
open my $fh, "| bc";
print $fh "2+2\n"; # not ok
close $fh;
close STDOUT;
open(STDOUT, ">&", $orig_stdout) || die $!;
print "$stdout_sink";
实际输出将是:
before bc
预期产量:
before bc
4
你在mob的答案中有一个详细的解释,为什么你不能将孩子的STDOUT
重定向到一个变量,这实际上不是一个文件句柄。
相反,您可以使用模块运行外部程序,这可以将标准流重定向到变量。 然后,您可以根据需要将字符串与重定向输出组合在一起。
IPC :: Run3的一个例子
use warnings;
use strict;
use feature 'say';
use IPC::Run3;
open my $fh, ">", \my $so_1;
my $old = select $fh; # make $fh the default for output,
say "To select-ed default"; # so prints end up in $so_1
run3 ["ls", "-l", "./"], undef, \my $so_2; # output goes to $so_2
select $old; # restore STDOUT as default for output
print $so_1, $so_2;
在这里,我使用select来操作默认打印的位置(没有指定文件句柄)。
请注意,例如重定向run3
在不同的变量( $so_2
),比使用以前的重定向的一个。 如果您更愿意附加到同一个变量,请在%options
指定
run3 ["ls", "-l", "./"], undef, \$so_1, { append_stdout => 1 };
并从打印语句中删除$so_2
。
该模块使用临时文件进行此重定向,正如回答中也指出的那样。
其他一些选项是Capture :: Tiny ,可以从几乎任何代码重定向输出,具有简单而干净的界面,以及非常强大,圆润,更复杂的IPC :: Run 。
这是不可能的。
管道打开和system
调用的标准输出被写入文件描述符1.通常,Perl的STDOUT
文件句柄与文件描述符1相关联,但可以对其进行操作。
在此示例中, system
调用写入STDOUT
文件句柄,写入文件foo
。
close STDOUT; # closes file descriptor 1
open STDOUT, '>', 'foo'; # reopens STDOUT as file descriptor 1
system("echo bar");
close STDOUT;
print STDERR "foo: ",`cat foo`;
# result: "foo: bar"
但在此示例中, system
调用写入BAZ
文件句柄。
close STDOUT; # closes file descriptor 1
open BAZ, '>', 'baz'; # attaches fd 1 to handle BAZ
open STDOUT, '>', 'foo'; # opens new file descriptor, maybe fd 3
system("echo bar");
close STDOUT;
print STDERR "foo: ",`cat foo`;
print STDERR "baz: ",`cat baz`;
# result: "foo: baz: bar"
内存中的文件句柄不是真正的文件句柄。 如果您在其上调用fileno
,您将(通常可能依赖于操作系统)获得负数。
open STDOUT, '>', \$scalar;
print STDERR fileno(STDOUT); # -1
管道打开并且系统调用将无法写入此文件句柄。
您将需要更复杂的解决方法,例如将管道打开输出写入文件,然后将该文件复制到内存中变量中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.