3

假设我想用“orange”替换“apple”这个词,用“apple”替换“orange”这个词我如何通过正则表达式在Perl中做到这一点?

这是我没有运气的代码:

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

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

我认为如果有某种方法可以终止 if 函数,如果它成功并且不再执行强制它返回到 while 循环的代码,那么上面的代码会起作用。但我确信有一种简单的正则表达式方法可以做到这一点。

4

2 回答 2

7

首先,永远不要使用$&变量:它会减慢正则表达式引擎的速度。另外,您不需要它;这相当于您当前的循环体:

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

但是,我们必须添加两点:

  1. 我们想替换所有出现的地方,而不仅仅是第一个匹配的单词。我们可以通过使用/g 标志来实现这一点。
  2. 我们希望在一次替换中执行此操作,以便替换不会变回。

我们可以通过使用将匹配字符串映射到替换的哈希来做到这一点:

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

lc小写匹配的字符串;这是必要的,因此Apple将被替换为orange. 保留大小写(以便我们得到Orange)可以通过删除不区分大小写的匹配并将 and 添加OrangeApple替换散列来实现。

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

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

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

于 2013-05-08T07:30:25.907 回答
3
my %look = (
  "apple" => "orange",
  "orange" => "apple",
);
my $rx = join "|", keys %look;

while (<MYFILE>) {
  s! ($rx) !$look{lc($1)}!xgi;
}
于 2013-05-08T07:35:10.000 回答