正则多行模式捕获最短匹配 解决起始模式重复导致匹配过长问题
问题原因
你原来使用的test2(.|\n)*?test4仅实现了基础的非贪婪匹配,只会从首个匹配到的test2开始向后查找最近的test4,不会过滤中间再次出现的起始标记test2,所以会出现跨起始标记匹配的错误结果。
解决方案
你可以通过负向先行断言限制匹配区间内不能再次出现起始标记test2,修改后的正则如下:
test2(?:(?!test2)[\s\S])*?test4
正则逻辑说明
[\s\S]匹配所有字符(包括换行符),比(.|\n)的写法执行效率更高(?!test2)是负向先行断言,要求当前位置之后不能出现字符串test2(?:(?!test2)[\s\S])*?表示非贪婪匹配任意字符,每匹配一个字符前都会校验后续是否出现test2,一旦遇到test2就会终止当前匹配段,自动从新的test2位置开始匹配- 最终刚好实现「只匹配相邻的test2到test4区间,不跨起始标记」的需求
匹配效果
用上述正则匹配你提供的测试文本,可直接得到符合预期的两组结果:
- 第一组匹配第7行
test2到第9行test4的内容 - 第二组匹配第12行
test2到第14行test4的内容
如果你的正则引擎支持单行(dotAll)模式,开启s修饰符后还可以简化为:
/test2(?:(?!test2).)*?test4/s
内容的提问来源于stack exchange,提问作者Budi
相关产品推荐
相关产品推荐

