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

rug*_*ted 3 regex perl

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

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

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

    if(/orange/i) {
        s/$&/apple/i;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

amo*_*mon 7

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

s/apple/orange/i;
s/orange/apple/i;
Run Code Online (Sandbox Code Playgroud)

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

  1. 我们想要替换所有出现的事件,而不仅仅是第一个匹配的字.我们可以通过使用/g 标志来实现这一点.
  2. 我们希望在一次替换中执行此操作,以便不会更改替换.

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

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

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

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

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

quotemeta逃逸的特殊字符,这样你可以从字面上匹配任意的字符串.