2009-10-07 80 views
7

如何使用Perl打印到變量?如何在Perl中打印到變量而不是文件?

我已經工作了一段程序,登錄高度詳細的時尚的迭代進步......

print $loghandle $some_message; 

不過,我想也有選擇地打印部分的消息發送到不同的文件。當然,我可以把代碼與...

print $loghandle $some_message 
print $otherloghandle $some_message 

或重寫整個業務成一個函數。等等。

我想要做的是做一些魔術當我打開$ loghandle這樣,當我print「ING,我其實只是在做一個sprintf十歲上下的操作對一個變量(稱之爲$current_iteration),使當我得到了一個決策點我可以做這樣的事情......

print $real_log_file $current_iteration; 
print $other_real_log_file $current_iteration if($condition); 

我相當肯定我見過像這樣的地方,但我不知道它在哪裏或在哪裏看。

編輯:File :: Tee在* nix上解決了這個問題,但我在Windows上運行。

+2

似曾相識? http://stackoverflow.com/questions/1532544/how-can-i-send-stdout-and-stderr-to-a-log-file-and-to-the-screen-in-win32-perl/1532691# 1532691 – 2009-10-07 21:30:43

+0

可能。我並沒有試圖真正開啓真正的流(儘管這並不重要);它更多地設置一個變量來充當目標流。我很懶,不想重寫50多條日誌消息,請參閱。 :-) – 2009-10-07 21:36:23

+2

@保羅·納丹我連接到布萊恩福伊的答案。使用Log4perl。將'$ condition'表示爲日誌記錄級別,定義操作。由於我沒有時間檢查它是如何工作的,所以我不會加入這個答案,但我會根據過去的經驗徹底推薦Log4perl。 – 2009-10-07 21:57:21

回答

18

您可以通過open治療標變量作爲文件句柄荷蘭國際集團它:

open my $fh, '>', \$variable or die "Can't open variable: $!"; 
print $fh "Treat this filehandle like any other\n"; 

你甚至可以映射標準輸出或標準錯誤的標量:

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

如果你w螞蟻分裂你的輸出或設置一個配置文件做你的日誌記錄的「有趣」的事情,你最好用Log4Perl像別人建議的那樣。

2

您可以使用File::Tee將文件句柄拆分爲多個輸出流。

use File::Tee; 
open my $fh, '>', 'logfile.txt' or die $!; 
tee($fh, '>', 'otherlogfile.txt') if $condition; 

print $fh $current_iteration; # will also go to otherlogfile.txt 
           # if $condition was true 
+0

我在Windows上運行(File :: Tee不)。再加上這個問題。 – 2009-10-07 21:26:09

1

聽起來像是想要tie您的文件句柄。

my $x; 

# printing to $fh will update the variable $x 
# when you close $fh, it will print $x to a filehandle depending 
# on code in the function Print_to_variable::CLOSE 

tie $fh, "Print_to_variable", \$x, $output_fh1, $output_fh2; 
print $fh "stuff"; 
print $fh "more stuff"; 
close $fh; 

sub Print_to_variable::TIEHANDLE { 
    my ($class, $ref, $fh1, $fh2) = @_; 
    my $self = {}; 
    $self->{ref} = $ref; 
    $self->{output_fh1} = $fh1; 
    $self->{output_fh2} = $fh2; 
    bless $self, "Print_to_variable"; 
    $self; 
} 
sub Print_to_variable::PRINT { 
    my ($self,@list); 
    ${$self->{ref}} .= join "", @list; 
} 
sub Print_to_variable::CLOSE { 
    my $self = shift; 
    my $text = ${$self->{ref}}; 
    if (&myCondition1($text)) { # ... how you decide where to print 
     print {$self->{output_fh1}} $text; 
    } else { 
     print {$self->{output_fh1}} $text; 
    } 
} 
+0

我是這麼認爲的,但我今天很愚蠢,看不到領帶如何在這裏工作。 – 2009-10-07 21:29:32

5

你的意思是說像IO::Scalar?讓你用文件句柄語義寫入一個變量。

+3

您不需要顯式地使用IO :: Scalar。 open()本身工作得很好。 – 2009-10-08 02:51:33

1

這是一個巨大的黑客,我認爲mobrule的解決方案或(特別是)思念的Log4Perl解決方案是我有空的時候去的方法。

但是,這是我使用的是什麼,作爲一個完成的事情:

sub print_to_var($$) { 
    my($rx_var, $scalar) = @_; 
    $$rx_var .= $scalar; 
} 


print_to_var \$logvar, $message; 

#...later on... 
print $somefile $logvar; 

編輯:

因爲這是社會的維基,它的價值沒有什麼是Perl別名函數參數。這意味着你可以這樣寫:

sub print_to_var($$) { 
    $_[0] .= $_[1]; 
} 

然後說:

my $foo = "OH HAI. "; 
print_to_var $foo, "I ARE HELO KITTIE."; 
say $foo; # OH HAI. I ARE HELO KITTIE. 

這並不是一個特別巨大的黑客,雖然print_to_var是一個很大的打字比.是。

這裏是HELO基蒂:

helo kittie http://blogs.philadelphiaweekly.com/style/files/2008/11/hello-kitty-color.gif

+0

我很開心!我不確定關於函數​​的別名/引用參數。謝謝! – 2009-10-09 01:56:09

4

如果要執行選擇性日誌記錄,您可以控制哪些消息被記錄以及記錄的位置,請使用Log::Log4perl。這會爲你節省一大堆時間,解決tie和其他黑魔法。