如何在Perl中关闭并重新打开STDOUT?

时间:2011-06-20 20:37:18

标签: perl cgi stdout

我想关闭STDOUT以防止我的代码输出我需要进一步计算但不想在我的网页上使用的特定图像。

所以我想关闭STDOUT,做我必须处理的代码,然后重新打开STDOUT将内容输出到网页。 (不是文件)

我尝试的是:

    close STDOUT;
    # my code here
    open STDOUT;

这不起作用......

由于

6 个答案:

答案 0 :(得分:11)

有几种方法可以解决您的问题,其中许多方法都不需要您关闭STDOUT并冒着满足程序标准I / O通道的风险。

例如,您可以使用(1-arg)select命令暂时将print命令的输出定向到其他位置。

 print $stuff_you_want_to_send_to_STDOUT;

 select(NOT_STDOUT);
 # now default print sends things to NOT_STDOUT.
 # This doesn't need to be a real filehandle, though you may get warning
 # messages if it is not.
 ...;
 print $the_image_you_dont_want_to_go_to_STDOUT;
 ...;

 select(STDOUT);
 # now  print  sends things to STDOUT agin
 print $more_stuff_you_do_want_to_go_to_STDOUT;

您也可以在运行时重新分配*STDOUT glob而不关闭任何句柄。

 *OLD_STDOUT = *STDOUT;
 print $for_STDOUT;

 *STDOUT = *NOT_STDOUT;     # again, doesn't need to be a real filehandle
 print $stuff_to_suppress;

 *STDOUT = *OLD_STDOUT;     # restore original STDOUT
 print $more_stuff_for_STDOUT;

答案 1 :(得分:6)

关闭STDOUT是不好的,因为很多人认为它始终是开放的。最好将其重定向到/dev/null(unix)或nul(Windows)。

如果要重定向文件描述符,

use Sub::ScopeFinalizer qw( scope_finalizer );

{
    open(my $backup_fh, '>&', \*STDOUT) or die $!;
    my $guard = scope_finalizer { open(STDOUT, '>&', $backup_fh) or die $!; };
    open(STDOUT, '>', '/dev/null') or die $!;

    ...
}

如果您只想重定向STDOUT,

{
    local *STDOUT;
    open(STDOUT, '>', '/dev/null') or die $!;

    ...
}

如果您只想重定向默认输出句柄,

use Sub::ScopeFinalizer qw( scope_finalizer );

{
    open(my $null_fh, '>', '/dev/null') or die $!;
    my $backup_fh = select($null_fh);
    my $guard = scope_finalizer { select($backup_fh); };

    ...
}

答案 2 :(得分:3)

你可以实现一些东西来捕捉STDOUT:

sub stdout_of (&) {
    my $code = shift;

    local *STDOUT;
    open STDOUT, '>', \(my $stdout_string = '')
        or die "reopen STDOUT: $!";

    $code->();

    return $stdout_string;
}

然后像这样使用它:

my $stdout = stdout_of { print "hello world" };

将文件句柄本地化为stdout_of()可以避免关闭和重新打开STDOUT的技巧。

答案 3 :(得分:2)

阅读documentation for open

搜索“这是一个使用各种方法保存,重定向和恢复STDOUT和STDERR的脚本”。

您要做的不是关闭STDOUT,而是暂时将其重定向到/ dev / null。

答案 4 :(得分:1)

要(重新)打开STDOUT或STDERR作为内存文件,请先关闭它:

 close STDOUT;
    open STDOUT, '>', \$variable or die "Can't open STDOUT: $!";

来自perl doc:http://perldoc.perl.org/functions/open.html 你有一个:关闭后,不要这样做。上面的开放也应该与jus

一起使用
open STDOUT;

Perl僧侣中的这个帖子也可以帮到你:http://www.perlmonks.org/?node_id=635010

答案 5 :(得分:1)

我检查了两种方式:

  1. 通过select
  2. 通过*OLD_STDOUT = * STDOUT,并查看它们在常见情况下无法使用。
  3. 原因是只有在Perl脚本中使用“print”或其他内容时,这两种方法才会重定向STDOUT。但是如果你使用“system()”调用或调用下标,他们的输出无论如何都得到标准的STDOUT =((。

    我的观点,确实解决方案是:

    #!/usr/bin/perl -w
    my $file1 = "/tmp/out.txt";
    my $file2 = "/tmp/err.txt";
    open my $oldSTDOUT, ">&STDOUT";
    open OLDERR, ">&",\*STDERR; 
    open(STDOUT, ">$file1")  or print("Can't redirect stdout: to $file1 ");
    open(STDERR, ">$file2")  or print("Can't redirect stderr: to $file2 ");
    print "THIS OUTPUT ISN'T GOT TO STANDARD OUTPUT\n";
    system("pwd"); # this output isn;t got to standard output too, that is right!
    close(STDOUT);
    close(STDERR);
    open STDOUT, ">>&", $oldSTDOUT;
    open STDERR, ">>&OLDERR"; 
    print "BUT THIS OUTPUT IS SEEN IN A STANDARD OUTPUT\n";
    

    我检查了这个解决方案,它对我有用。