带负向先行断言的贪婪可重复捕获组失效问题排查
正则表达式匹配问题分析与解决
你的正则((?:test)+)(?!$)本意是仅当最后一个重复的test不位于字符串末尾时才匹配,预期匹配sometesttesttesta,不匹配sometesttesttest,但实际后者里会匹配到testtest,问题出在正则的回溯机制上。
原因详解
正则的贪婪匹配会先尽可能多地捕获test——比如在sometesttesttest里,会先匹配全部三个test。但此时匹配内容的末尾就是字符串结尾$,不满足(?!$)的负向断言条件。这时候正则会触发回溯:放弃最后一个test的匹配,此时剩下的两个test后面跟着的是第三个test(不是字符串结尾),刚好满足(?!$),所以就匹配到了testtest。
解决方案
要实现你的需求,需要避免正则通过回溯“凑”出满足断言的匹配结果,以下两种方法可以解决:
使用原子组禁止回溯(适用于PCRE等支持原子组的正则引擎):
((?>test)+)(?!$)原子组
(?>...)会锁定内部的匹配结果,禁止回溯。一旦匹配了所有test后发现不满足(?!$),就直接判定匹配失败,不会再减少匹配的test数量。调整断言逻辑(通用型写法,适配多数正则引擎):
(test)+(?=.+$)这个正则表示:匹配一个或多个
test,且后面必须存在至少一个任意字符(即匹配内容不在字符串末尾)。这样在sometesttesttest中,全部三个test后面是结尾,不满足(?=.+$),直接不匹配;而sometesttesttesta中,三个test后面有a,满足条件,就会匹配完整的testtesttest。
内容的提问来源于stack exchange,提问作者silkfire
相关产品推荐
相关产品推荐

