有没有办法将子例程的打印输出捕获到变量,以便我可以将其发送到 stderr?



假设:

sub test {
        print "testingn";
}

如果有一种情况,我想让它打印到stderr而不是stdout,有没有一种方法我可以调用子例程来做到这一点?或者我可以捕获输出到一个变量,然后使用警告?我对perl还是个新手。

有。print将其输出发送到"选定的"文件句柄,通常是STDOUT。但是Perl提供了select函数,您可以修改它。

select(STDERR);
&test;           # send output to STDERR
select(STDOUT);  # restore default output handle

select函数返回先前选择的文件句柄,因此您可以捕获它并在以后恢复它。

my $orig_select = select(STDERR);
&test;
select($orig_select);

Perl通过local()的动态作用域并不常用,但我觉得这是一个很好的应用程序:

test(); # to stdout
{
    open(local *STDOUT, ">&STDERR") or die "dup out to err: $!";
    test(); # to stderr, locally calling it "STDOUT"
}
test(); # to stdout again

test()的调用——以及test()本身可能调用的任何东西——将使STDOUT动态作用域为STDERR的副本。当控制离开块时,即使通过die(), STDOUT也会恢复到块

之前的状态。广义:

sub out2err(&) {
  my $user_block = shift;
  open(local *STDOUT, ">&STDERR") or die $!;
  $user_block->();
}
test();             # to stdout
out2err { test() }; # to stderr
test();             # to stdout

同时,您还可以"将子例程的打印输出捕获到一个变量"。

传递一个标量给open:

#! /usr/bin/env perl
use common::sense;
use autodie;
sub tostring (&) {
  my $s;
  open local *STDOUT, '>', $s;
  shift->();
  $s
}
sub fake {
  say 'lalala';
  say 'more stuff';
  say 1 + 1, ' = 2';
  say for @_;
}
for (tostring { fake(1, 2, 3) }) {
  s/n/\n/g;
  say "Captured as string: >>>$_<<<";
}
输出:

Captured as string: >>>lalalanmore stuffn2 = 2n1n2n3n<<<

这是我的工作

local *STDOUT;
open(STDOUT, ">", $Result);
&test();
print $Result;

最新更新