如何优化匹配任意顺序非相邻两指定字符串的正则表达式
正则表达式优化方案
原有写法的可优化点
- 冗余度高:两个关键词重复书写两次,若关键词为长字符串,修改时需要同步改两处,容易出现笔误
- 间隔阈值需要配置两次:调整两个词之间的最大间隔字符数时,需要修改两处的
150,维护成本高 - 无词边界限定:默认会匹配到包含目标关键词的更长字符串(比如
arranger里的ranger、cowboys里的cowboy),若需要匹配完整单词需要补充边界规则
通用优化写法(兼容所有主流正则引擎)
(ranger|cowboy)(?:.{0,150})(?!\1)(?:ranger|cowboy)
写法说明
- 第一个捕获组
(ranger|cowboy):从左到右匹配第一个出现的任意一个关键词 (?:.{0,150}):匹配两个关键词之间最多150个任意字符,?:表示该组不需要捕获,减少性能开销(?!\1):负向先行断言,确保后续匹配的关键词和第一个捕获组的关键词不是同一个,自动排除同词重复匹配的场景(比如两个ranger连续出现的情况不会被误匹配)- 最后的
(?:ranger|cowboy):匹配第二个不同的关键词 - 所有关键词只需要书写一次,后续修改关键词或者间隔阈值时仅需要调整一处即可
匹配测试验证
- 输入
The cowboy was made a ranger.:第一个捕获组匹配cowboy,中间间隔字符数远小于150,最后匹配ranger,正常命中 - 输入
Not all rangers are good cowboys.:无词边界的写法会匹配到ranger(来自rangers的前6个字符)和cowboy(来自cowboys的前6个字符),和原有写法表现完全一致
适配不同需求的调整方案
- 若需要仅匹配完整单词,补充词边界
\b避免误匹配:(\branger\b|\bcowboy\b)(?:.{0,150})(?!\1)(?:\branger\b|\bcowboy\b) - 若需要支持跨行匹配(两个词中间包含换行符),需要开启正则的dotall模式(不同语言开启方式不同:JS在正则后加
s修饰符,Python调用re.DOTALL参数,Java用Pattern.DOTALL),此时.可以匹配换行符 - 若需要支持匹配单复数形式,可直接调整关键词为
rangers?、cowboys?即可
方案对比
该优化写法和原有写法功能完全等价,适配所有测试场景。若关键词很短,原有写法可读性较好,性能差异可忽略;若关键词较长或者后续频繁调整规则,优化写法的维护成本优势非常明显。
内容的提问来源于stack exchange,提问作者Ozzie
相关产品推荐
相关产品推荐

