2013-10-24 53 views
2

我有一個子程序在eval表達式中對format進行了刪除。如果這個子程序被多次調用,perl會警告已經重新定義了一種格式。避免在eval中重新定義perl格式

此代碼:

use warnings; 
routine(); 
routine(); 

sub routine{ 
    my $s = "FAIL"; 
    my $def = "format =\[email protected]<<<<@>>>>\n\$s, \$s\n."; 
    eval $def; 
    write; 
} 

打印

FAIL FAIL 
Format STDOUT redefined at (eval 2) line 1. 
FAIL FAIL 

是否有可能在子程序結束時刪除格式的聲明?

+1

你有沒有考慮過使用Perl6 :: Form?必須更好。完全避免這個問題。 – ikegami

+2

'使用診斷;' – mob

+0

我只是試圖快速修復一個古老的模塊。我很確定開發者沒有想到這個子被稱爲不止一個。原來這是錯誤的:) – ajwood

回答

1

這是一個簡單的解決方案,它使用一個標誌來避免重新定義格式。

use strict; 
use warnings; 

routine(); 
routine(); 

my $format_defined; 

sub routine{ 
    my $s = "FAIL"; 
    if (!$format_defined) { 
     my $def = "format =\[email protected]<<<<@>>>>\n\$s, \$s\n."; 
     eval $def; 
     $format_defined = 1; 
    } 
    write; 
} 

這是一個更復雜的解決方案,允許爲每次調用重新定義格式。它使用臨時文件句柄代替STDOUT,將輸出重定向到標量,然後您可以打印到標準輸出。

routine('FAIL'); 
routine('PASS'); 

sub routine{ 
    my $s = shift; 

    format REPORT = 
@<<<<@>>>> 
$s, $s 
. 
    my $report; 
    open my $fh, '>', \$report; 
    select $fh; 
    $~ = 'REPORT'; 
    write; 
    close $fh; 

    select STDOUT; 
    print $report; 
}