如何在Perl中通过正则表达式替换

时间:2013-05-08 07:16:02

标签: regex perl

假设我想用“橙色”替换“apple”这个词,用“apple”替换“orange”这个词,我怎么用Perl通过正则表达式做到这一点?

这是我的代码,我没有运气:

while (<MYFILE>) {
    if (/apple/i) {
        s/$&/orange/i;
    }

    if(/orange/i) {
        s/$&/apple/i;
    }
}

上面的代码可以工作我想如果有某种方法来终止if函数,如果它是成功的,并且不再执行代码强制它返回到while循环。但我确定这是一种简单的正则表达方式。

2 个答案:

答案 0 :(得分:7)

首先,从不使用$&变量:它会降低正则表达式引擎的速度。而且,你不需要它;这相当于你当前的循环体:

s/apple/orange/i;
s/orange/apple/i;

但是,我们必须增加两个:

  1. 我们希望替换所有出现的内容,而不仅仅是第一个匹配的单词。我们可以使用/g标志来实现这一点。
  2. 我们希望在一次替换中执行此操作,以便不会更改替换。
  3. 我们可以通过使用将匹配的字符串映射到替换的哈希来实现:

    my %replacement = (
      apple  => 'orange',
      orange => 'apple',
    );
    while (<>) {
      s/(apple|orange)/$replacement{lc $1}/ig;
      print;
    }
    

    lc小写匹配的字符串;这是必要的,以便将Apple替换为orange。通过删除不区分大小写的匹配并将OrangeOrange添加到替换哈希,可以实现保留外壳(以便我们获得Apple)。

    现在,如果你的哈希有大量的替换,我们不想手动编写正则表达式(只是很多静态替代)。我们可以从哈希中创建正确的正则表达式,如

    my $re = join '|', map quotemeta, keys %replacement;
    while (<>) {
      s/($re)/$replacement{$1}/g;
    }
    

    quotemeta转义特殊字符,以便您可以按字面匹配任意字符串。

答案 1 :(得分:3)

my %look = (
  "apple" => "orange",
  "orange" => "apple",
);
my $rx = join "|", keys %look;

while (<MYFILE>) {
  s! ($rx) !$look{lc($1)}!xgi;
}