$s = "bla..bla";
$s =~ s/([^%])\./$1/g;
我认为它应该将所有出现的.
that is not after%
替换为 before 的字符.
。
But $s
is then: bla.bla
, 但它应该是blabla
. 问题出在哪里?我知道我可以使用量词,但我需要这样做。
当全局正则表达式搜索字符串时,它不会找到重叠的匹配项。
字符串中的第一个匹配项将是a.
,替换为a
。当正则表达式引擎恢复搜索时,它从下一个开始,.
所以它看到.bla
视为字符串的其余部分,并且您的正则表达式需要一个字符在之前匹配,.
因此它不能再次匹配。
相反,使用否定的lookbehind来执行前一个字符不是的断言%
:
$s =~ s/(?<!%)\.//g;
请注意,如果您使用积极的后视,如果它是字符串中的第一个字符(?<=[^%])
,您将不会替换它。.
问题是即使有了/g
标志,每次替换都会开始查找前一个替换的位置。您尝试替换a.
为a
,然后a.
替换为a
,但第二次替换没有发生,因为a
已经被前一次替换“吞下”。
一种解决方法是使用零宽度后向断言:
$s =~ s/(?<=[^%])\.//g;
这将删除任何.
不是字符串中第一个字符且前面没有.%
但你可能真的想要这个:
$s =~ s/(?<!%)\.//g;
即使它是字符串中的第一个字符,它将删除任何不.
以开头的字符。%
比look-behinds简单得多的是使用:
$s =~ s/([^%])\.+/$1/g;
这将替换字符后的任何一个或多个点的字符串,而不是%
什么都没有。