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

Eli*_*Eli 25 perl

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

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

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

想法?

ike*_*ami 37

一些方法(globs):

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

if ($output) {
   open(OUTPUT, '>', $output) or die;
} else {
   *OUTPUT = *STDOUT;
}
Run Code Online (Sandbox Code Playgroud)

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

一些方法(词汇变量):

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

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

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

某些方式(其他):

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

  • `...} else {open($ fh,'>&'.fileno(STDOUT)); }` (2认同)

Dav*_*idO 10

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

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

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

STDOUT使用三个arg 打开欺骗的正确方法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.';
Run Code Online (Sandbox Code Playgroud)

或者传递STDOUTopentypeglob作为参考:

open my $fh, '>&', \*STDOUT or ...
Run Code Online (Sandbox Code Playgroud)


dax*_*xim 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}";
Run Code Online (Sandbox Code Playgroud)
perl foo -o blahblah        # opens file blahblah for writing
perl foo -o -               # goes to STDOUT
Run Code Online (Sandbox Code Playgroud)

相关:有没有理由在Perl中使用open(...)的双参数形式?