如何用其前辈替换所有出现的某些字符?

时间:2013-02-20 17:17:21

标签: perl regex

$s = "bla..bla";
$s =~ s/([^%])\./$1/g;

我认为它应该用.之前的字符替换所有不在%之后的.

但是$s是:bla.bla,但是  它应该是blabla。问题出在哪儿?我知道我可以使用量词,但我需要这样做。

3 个答案:

答案 0 :(得分:9)

当全局正则表达式搜索字符串时,它将找不到重叠匹配。

字符串中的第一个匹配项为a.,后面会替换为a。当正则表达式引擎恢复搜索时,它会从下一个.开始,因此它会将.bla视为字符串的其余部分,并且您的正则表达式需要在.之前匹配一个字符,因此它无法匹配试。

相反,使用负面的lookbehind来执行前一个字符不是%的断言:

$s =~ s/(?<!%)\.//g;

请注意,如果您使用(?<=[^%])之类的正面后瞻,如果它是字符串中的第一个字符,则不会替换.

答案 1 :(得分:6)

问题是即使使用/g标志,每次替换都会开始查看前一个替换的位置。您尝试将a.替换为a,然后将a.替换为a,但第二次替换不会发生,因为a已经“被以前的替换吞下了。

一种解决方法是使用zero-width lookbehind assertion

$s =~ s/(?<=[^%])\.//g;

将删除字符串中的第一个字符的任何.,并且 not 前面有%

但你可能真的想要这个:

$s =~ s/(?<!%)\.//g;

将删除{em>之前 .,即使 是字符串中的第一个字符。

答案 2 :(得分:3)

比后视更简单的是使用:

$s =~ s/([^%])\.+/$1/g;

这将替换除%以外的字符后的任何一个或多个点的任何字符串。