Perl正则表达式替换字符串特殊变量

时间:2009-11-21 22:36:24

标签: regex perl

我知道匹配,prematch和postmatch预定义变量。我想知道s ///运算符的评估替换部分是否有类似的东西。

这在动态表达式中特别有用,因此不必在第二次进行评估。

例如,我目前有%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 {$ key} {'replace'}可能是字符串'“$ 2 $ 1”'因此交换了某些文字的位置string $ regexs {$ key} {'search'}可能是'(foo)(bar)' - 因此导致“barfoo”。我试图避免的第二个评估是$ regexs {$ key} {'replace'}的输出。

4 个答案:

答案 0 :(得分: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 :(得分:1)

我很确定没有任何直接的方法来做你所要求的,但这并不意味着它是不可能的。怎么样?

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

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

好吧,除了要做得非常好,你必须在那里做一些代码,以便在一个单一的字符串(反斜杠单引号和反斜杠)中使哈希值保持安全。

答案 2 :(得分:1)

如果您手动执行第二个eval,则可以自行存储结果。

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

答案 3 :(得分:0)

为什么不在之前分配到本地变量:

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

现在你的评估一次。