2009-11-21 236 views
2

我知道匹配,prematch和postmatch預定義變量。我想知道是否有類似的s ///運算符的評估替換部分。Perl正則表達式替換字符串特殊變量

這將在動態表達式中特別有用,因此不必在第二次進行評估。

例如,我目前有%regexs這是各種搜索和替換字符串的散列。

這裏有一個片段:

while (<>) { 
    foreach my $key (keys %regexs) { 
    while (s/$regexs{$key}{'search'}/$regexs{$key}{'replace'}/ee) { 
     # Here I want to do something with just the replaced part 
     # without reevaluating. 
    } 
    } 
    print; 
} 

有沒有一種方便的方法來做到這一點? Perl似乎有這麼多便捷的捷徑,而且要評估兩次似乎是一種浪費(這似乎是另一種選擇)。

編輯:我只是想舉一個例子:$ regexs {$鍵} {「取代」}可能是字符串「‘$ 2 $ 1’」,從而換入字符串$ regexs一些文本的位置{ $ key} {'search'}可能是'(foo)(bar)' - 從而導致「barfoo」。我試圖避免的第二個評估是$ regexs {$ key} {'replace'}的輸出。

回答

0

爲什麼不前分配給本地變量:

my $replace = $regexs{$key}{'replace'}; 

現在你的評估一次。

+0

Thx,但我的問題可能不清楚。我使用/ ee修飾符來評估$ regexs {$ key} {'replace'}的計算結果,這可能取決於$ regexs {$ key} {'search'}。 – 2009-11-21 22:58:45

2

而不是使用字符串eval(我認爲是s///ee發生了什麼),您可以定義代碼引用來完成這項工作。那些代碼引用可以返回替換文本的值。例如:

use strict; 
use warnings; 

my %regex = (
    digits => sub { 
     my $r; 
     return unless $_[0] =~ s/(\d)(\d)_/$r = $2.$1/e; 
     return $r; 
    }, 
); 

while (<DATA>){ 
    for my $k (keys %regex){ 
     while (my $replacement_text = $regex{$k}->($_)){ 
      print $replacement_text, "\n"; 
     } 
    } 
    print; 
} 

__END__ 
12_ab_78_gh_ 
34_cd_78_yz_ 
1

我很確定沒有任何直接的方法來做你所要求的,但這並不意味着這是不可能的。這個怎麼樣?

{ 
    my $capture; 
    sub capture { 
    $capture = $_[0] if @_; 
    $capture; 
    } 
} 

while (s<$regexes{$key}{search}> 
     <"capture('" . $regexes{$key}{replace}) . "')">eeg) { 
    my $replacement = capture(); 
    #... 
} 

嗯,除了做真正正確的,你不得不鞋拔子多一點的代碼在那裏進行的哈希值singlequotish字符串(反斜槓singlequotes和反斜線)內是安全的。

1

如果您手動執行第二個評估,您可以自行存儲結果。

my $store; 
s{$search}{ $store = eval $replace }e; 
+0

儘管最後的$存儲是多餘的,賦值返回分配的值。 – cjm 2009-11-23 05:10:30

+0

啊,真的。也是多餘的。 – Schwern 2009-11-23 23:41:43