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

发布于 2024-10-07 17:48:32 字数 389 浏览 9 评论 0原文

我想将 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.
}

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

I want to redirect STDERR and STDOUT to a variable. I did this.

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.
}

The problem with system. I want the output of this call to be captured too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

明明#如月 2024-10-14 17:48:32

您是否正在寻求捕获变量中的输出?如果是这样,您可以使用反引号或 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 不知道如何合作。

Are you seeking to capture the output in a variable? If so, you have use backticks or qx{} with appropriate redirection. For example, you could use:

#/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";
}

(I happen to have programs pth1, pth2 and pth3 in the directory - they were made OK; pth4 and above write errors to stderr; the redirection was necessary.)

You should always check the success of operations such as open().

Why is this necessary? Because writing to a variable requires the cooperation of the process doing the writing - and make doesn't know how to cooperate.

玩套路吗 2024-10-14 17:48:32

有多种方法重定向并恢复 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";

享受。

There are several ways to redirect and restore STDOUT. Some of them work with STDERR too. Here are my two favorites:

Using select:

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

Using local:

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

Enjoy.

不美如何 2024-10-14 17:48:32

为什么不使用 IPC::Open3

Why not use IPC::Open3?

十二 2024-10-14 17:48:32

TLDR 答案

使用 Capture::Tiny;< /strong>

合并 STDOUT 和 STDERR

如果您想要 STDOUT (来自 print()s)和 STDERR (来自 warn()< /code>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

Eval @result 的结果

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

TLDR Answer

use Capture::Tiny;

Merged STDOUT and STDERR

If you want STDOUT (from print()s) and STDERR (from warn()s) to be merged, then use...

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

Separated STDOUT and STDERR

If you want them separated...

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

Results of Eval

@result indicates the success, with success being [1], and failure being []. Tiny has a ton of other functions that you can look through for other cases, like code references, etc.. But I think the code above should cover most of any Perl developer's needs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文