2009-11-21 161 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