2011-06-20 46 views
9

我想關閉標準輸出,以防止我的代碼outputing,我需要進一步的計算,但不希望我的網頁上的特定圖像。如何關閉和Perl中重新打開STDOUT?

因此,我想關閉STDOUT,做我的代碼,然後重新打開STDOUT輸出的東西到網頁。 (不是一個文件)

我想的是:

close STDOUT; 
    # my code here 
    open STDOUT; 

這不工作...

感謝

+2

你爲什麼不避免打印你不想打印的東西? – cjm

+0

我使用cgi_png(),它不可避免地打印圖形 – Italics

+0

然後使用scalar_png代替。它返回cgi_png將打印的圖像(CGI頭除外)。 – cjm

回答

9

有幾種方法可以解決您的問題,其中許多方法並不要求您關閉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水珠而不關閉任何手柄。

*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; 
2

閱讀documentation for open

搜索「這裏是保存,重定向,並恢復使用各種方法STDOUT和STDERR的腳本」。

你想要做什麼不緊密STDOUT,而是臨時重定向到/ dev/null的。

5

是不好的關閉標準輸出,因爲很多假定它是常開。這是更好地重定向到/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); }; 

    ... 
} 
+1

如果不清楚,無論塊如何退出,所有東西都會在塊的末尾自動恢復正常。 – ikegami

1

我檢查了2種方法:

    經由 select
  1. 經由*OLD_STDOUT = * STDOUT,看看它們不常見情況下可用。

原因是這兩種方法僅在Perl腳本中使用「打印」或其他東西時重定向STDOUT。但是如果你使用「系統()」呼叫或撥打標,它們的輸出得到了標準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"; 

我檢查這個解決方案,它爲我工作

2

您可以實現的東西趕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的技巧。