如何在Perl中将文件句柄指向STDOUT(或另一个文件句柄)?

时间:2011-06-09 17:00:09

标签: perl

我想创建一个快速脚本,如果给出文件则写入文件,如果没有给出文件则写入stdout。如果我可以通过将新文件句柄OUTFILE指向适当的任何一个来启动脚本,那么这样做会容易得多。

我知道我可以通过在适当的时候将STDOUT指向我的输出文件来完成我想要的工作,但我宁愿不这样做,因为我不想让以后使用该脚本的任何人感到困惑,并想知道为什么他们的打印声明不要不行。此外,我仍然希望自己偶尔使用打印声明进行故障排除,并且永远不要将此打印输出到输出文件。

所有这些都说,我正在寻找的是: open( OUTFILE, ($output ? ">$output" : STDOUT );
除了不起作用。

想法?

5 个答案:

答案 0 :(得分:37)

某些方式(globs):

# Requires 2-arg open, unfortunately
open(OUTPUT, "> ".($output || '-'))  or die;

if ($output) {
   open(OUTPUT, '>', $output) or die;
} else {
   *OUTPUT = *STDOUT;
}

if ($output) {
   open(OUTPUT, '>', $output) or die;
} else {
   open(OUTPUT, '>&', \*STDOUT) or die;
}

某些方式(词汇变量):

# Requires 2-arg open, unfortunately
open(my $fh, "> ".($output || '-'))  or die;

my $fh;
if ($output) {
   open($fh, '>', $output) or die;
} else {
   $fh = \*STDOUT;
}

my $fh;
if ($output) {
   open($fh, '>', $output) or die;
} else {
   open($fh, '>&', \*STDOUT) or die;
}

某些方式(其他):

# Changes the default handle for <print "foo">.
if ($output) {
   open(OUTPUT, '>', $output) or die;
   select(OUTPUT);
}

答案 1 :(得分:10)

为了读者的缘故(因为OP已经“开始工作”):

Perl文档,“perlopentut”(perldoc perlopentut)给出了打开一个指向STDOUT的备用文件句柄的示例,但它使用了裸字文件句柄和open的两个arg版本,两者都有点古老。 Damian Conway的书“Perl Best Practices”(以及Perl :: Critic,基于Damian的书)强调使用三个arg打开和词法文件句柄(my $foo样式文件句柄)。 chromatic的“Modern Perl”也简要提到了使用词法文件句柄,并且在实际可行的情况下不鼓励使用。三个arg open被认为是一种更安全的形式,因为它限制了外壳注射的暴露。虽然这里的具体案例风险较低,但默认为3-arg open仍然是一个好习惯。

仔细阅读Perl的open文档(perldoc -f open)中显示的示例,并稍微解释一下,在打开指向{{1}的重复的手柄时,注意到&符号的正确位置当使用STDOUT的三个arg版本时。有人可能会错误地认为这应该有效:open,主要是因为它看起来像我们习惯看到的格式(符号名称前面的符号)。但是这种语法不是open my $fh, '>', '&STDOUT' or die $!;所需要的,我们习惯于在完全不同的上下文中看到它:某些子例程调用。

使用三个arg openSTDOUT打开欺骗的正确方法是将open>合并到同一个参数中,并保留STDOUT裸露,像这样:

&

或将use Modern::Perl; open my $fh, '>&', STDOUT or die "Bleah: $!"; say $fh 'Printing alternate filehandle "$fh" worked.'; say 'Implicitly printing to "STDOUT" also works.'; 传递给STDOUT作为对typeglob的引用:

open

答案 2 :(得分:7)

-很神奇。遵循惯例或违反最少惊喜的原则。

use autodie qw(:all);
use Getopt::Long qw(GetOptions);
GetOptions(\my %opt, 'out=s') or die 'usage';
die 'usage' unless $opt{out};
open my $handle, ">$opt{out}";

perl foo -o blahblah        # opens file blahblah for writing
perl foo -o -               # goes to STDOUT

相关:Are there reasons to ever use the two-argument form of open(...) in Perl?

答案 3 :(得分:4)

没关系。弄清楚了。投入一个&符可以解决问题。完整的工作代码是:
open( OUTPUT, ( $output ? ">$output" : ">&STDOUT" ) );

答案 4 :(得分:3)

您可以随时将常规输出写入STDOUT,将调试语句写入STDERR。然后,如果用户希望输出转到文件,他们只需将STDOUT重定向到命令行上的文件。

相关问题