在“写入STDOUT”和“写入outfile”之间寻找一个简单的切换

时间:2014-12-15 13:01:29

标签: perl io

对于我正在尝试用perl编写的程序,我想构建一个使输出转到输出文件的选项,这对于perl模块Getopt来说非常简单。但是,如果没有使用该选项,我希望输出转到终端(STDOUT)。因为我写了一个小脚本来测试我是否可以使用模块IO :: File构建一个开关。

#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Long;
use IO::File;

my $outfilename;

GetOptions (
    "out=s" => \$outfilename,
);

my $out = IO::File->new(">$outfilename");

if (defined $out) {
    print $out "Hello World!\n";
}
else {
    print "Hello World!\n";
}

close $out if $outfilename;

虽然该计划"运行"有或没有-o选项,当我在没有-o的情况下运行时,perl告诉我第13行中的$ outfilename未初始化,我猜是因为Getopt将变量返回为" false"何时不使用该选项。但是,我想不出办法绕过这个。你能帮助我吗? 另外,我绝对相信有一种更容易的方法来构建我不知道的这种开关。我只是写这篇文章是因为我无法找到更好的在线方式,所以如果你们有任何关于如何做到更聪明的提示,我将非常感激!

4 个答案:

答案 0 :(得分:4)

您收到警告是因为您无条件地使用$outfilename作为文件名,即使它仅在提供--out时具有值。

不要将整个print放在if中。如果你这样做,你最终会得到大量重复的代码。创建一个在所有条件下初始化的文件句柄

my $outfh;
if (defined($outfilename)) {
   open($outfh, '>', $outfilename)
      or die($!);
} else {
   $outfh = \*STDOUT;
}

print $outfh "Hello World!\n";

或重定向STDOUT

if (defined($outfilename)) {
   open(STDOUT, '>', $outfilename)
      or die($!);
}

print "Hello World!\n";

但是你为什么不从外面重定向STDOUT?

script >script.log

答案 1 :(得分:4)

您可以使用select设置默认输出文件句柄。这将使print自动打印到select ed文件句柄。

if ($outfilename) {
    open my $outfh, ">", $outfilename 
       or die "Cannot open $outfilename for output: $!";
    select $outfh;
}

print "Hello world!\n";

答案 2 :(得分:0)

您可以用文件句柄替换STDOUT,然后正常打印。

if($outfilename) {
    open my $of, ">", $outfilename;
    *STDOUT = $of;
}

print "Hello World!\n";

答案 3 :(得分:-1)

你最好看看以下内容:

select调用可让您重新定义print调用的默认文件处理程序。 SelectSaver允许您在给定代码块的范围内执行相同的操作。

在您的情况下,您可以重写代码,以便在运行将执行输出的代码之前,根据需要创建输出文件句柄并select。反过来,输出代码只会在没有文件句柄的情况下调用print