【发布时间】:2013-05-12 23:44:40
【问题描述】:
假设我们有:
sub test {
print "testing\n";
}
如果我想让它打印到 stderr 而不是 stdout,有没有办法可以调用子例程来执行此操作?或者我可以将输出捕获到变量然后使用警告吗?我对 perl 还很陌生。
【问题讨论】:
假设我们有:
sub test {
print "testing\n";
}
如果我想让它打印到 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()ing,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
【讨论】:
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: >>>lalala\nmore stuff\n2 = 2\n1\n2\n3\n<<<
【讨论】:
这对我有用
local *STDOUT;
open(STDOUT, ">", \$Result);
&test();
print $Result;
【讨论】:
do { local *STDOUT; open(STDOUT, ">", \$Result); &test(); }; print $Result;