如何将STDOUT和STDERR重定向到变量

时间:2010-12-11 06:19:11

标签: perl system stdout stderr redirect

我想将STDERRSTDOUT重定向到变量。我做到了。

close(STDOUT);
close(STDERR);

my $out;
open(STDOUT, ">>", \$out);
open(STDERR, ">>", \$out);

for(1..10)
{
    print "print\n"; # this is ok. 
    warn "warn\n"; # same
    system("make"); # this is lost. neither in screen nor in variable.
}

system的问题。我也希望捕获此调用的输出。

6 个答案:

答案 0 :(得分:13)

使用Capture::Tiny

答案 1 :(得分:4)

您是否想要在变量中捕获输出?如果是这样,您可以使用反引号或qx{}进行适当的重定向。例如,您可以使用:

#/usr/bin/env perl
use strict;
use warnings;

# Ensure we have a way to write messages
open my $fh, '>', "output" or die;

close(STDOUT);
close(STDERR);

my $out;
open(STDOUT, ">>", \$out) or do { print $fh, "failed to open STDOUT ($!)\n"; die };
open(STDERR, ">>", \$out) or do { print $fh, "failed to open STDERR ($!)\n"; die };

foreach my $i (1..10)
{
    print "print $i\n"; 
    warn "warn $i\n";
    my $extra = qx{make pth$i 2>&1};
    print $fh "<<$i>><<$out>><<$extra>>\n";
}

(我碰巧在目录中有程序pth1,pth2和pth3 - 它们没问题; pth4及以上写错误给stderr;重定向是必要的。)

您应该始终检查open()等操作是否成功。

为什么这有必要?因为写一个变量需要写作过程的合作 - make不知道如何合作。

答案 2 :(得分:3)

redirect and restore STDOUT有几种方法。其中一些也与STDERR一起使用。这是我最喜欢的两个:

使用select

my $out;
open my $fh, ">>", \$out;
select $fh;
print "written to the variable\n";
select STDOUT;
print "written to original STDOUT\n";

使用local

my $out
do {
    local *STDOUT;
    open STDOUT, ">>", \$out;
    print "written to the variable\n";
};
print "written to original STDOUT\n";

享受。

答案 3 :(得分:2)

发生这种情况的原因是STDOUT和STDERR“文件句柄”等同于shell提供给perl二进制文件的stderr和stdout句柄。为了达到您的目的,您应该使用open代替system

答案 4 :(得分:1)

为什么不use IPC::Open3

答案 5 :(得分:0)

TLDR 答案

use Capture::Tiny;

合并 STDOUT 和 STDERR

如果您希望合并 STDOUT(来自 print()s)和 STDERR(来自 warn()s),请使用...

my ($merged,  @result) = capture_merged { print "Hello, world!" };  # static code
my ($merged,  @result) = capture_merged { eval $codetoeval };       # code in variable

分离的 STDOUT 和 STDERR

如果你想让它们分开...

my ($stdout, $stderr, @result) = capture { print "Hello, world!" };   # static code
my ($stdout, $stderr, @result) = capture { eval $codetoeval };        # code in variable

评估结果

@result 表示成功,成功为[1],失败为[]。 Tiny 有大量其他功能,您可以查看其他情况,例如代码引用等。但我认为上面的代码应该可以满足任何 Perl 开发人员的大部分需求。