代码之家  ›  专栏  ›  技术社区  ›  Keith Bentrup

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

  •  1
  • Keith Bentrup  · 技术社区  · 15 年前

    我知道match、prematch和postmatch预定义变量。我想知道s///运算符的已评估替换部分是否有类似的内容。

    这在动态表达式中特别有用,因此它们不必进行第二次求值。

    下面是一个片段:

    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',从而交换字符串$regexs{$key}{'search'}中某些文本的位置,可能是''foo'(bar)'-从而产生“barfoo”。我试图避免的第二个计算是$regexs{$key}{'replace'}的输出。

    4 回复  |  直到 15 年前
        1
  •  2
  •   FMc TLP    15 年前

    而不是使用字符串 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_
    
        2
  •  1
  •   hobbs    15 年前

    {
      my $capture;
      sub capture {
        $capture = $_[0] if @_;
        $capture;
      }
    }
    
    while (s<$regexes{$key}{search}>
            <"capture('" . $regexes{$key}{replace}) . "')">eeg) {
      my $replacement = capture();
      #...
    }
    

    好吧,除了要真正正确地执行之外,您还必须在其中插入更多的代码,以使散列中的值在单引号字符串(反斜杠单引号和反斜杠)中安全。

        3
  •  1
  •   Schwern    15 年前

    my $store;
    s{$search}{ $store = eval $replace }e;
    
        4
  •  0
  •   ennuikiller    15 年前

    为什么不在以下情况之前分配给本地变量:

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

    现在你的评估一次。