如何编写仅无前置带任意间隔符的foo时匹配bar的正则表达式
正则匹配解决方案
适用支持可变长度负向后顾的引擎
部分现代正则引擎(.NET、Python 3.10+、Java 9+、PHP 7.3+)本身支持可变长度的后视断言,你最初的写法可以直接生效:
(?<!foo[\s\-/]*)bar
如果需要严格匹配独立单词,避免命中barbecue这类包含bar的词汇,可以补充单词边界:
(?<!foo[\s\-/]*)bar\b
全引擎兼容方案(不依赖可变长度后视)
针对JavaScript、Python 3.9及更早版本等不支持可变长度后视的引擎,可以用全局匹配锚点+否定前瞻+\K截断的写法实现需求:
\G(?:(?!foo[\s\-/]*bar).)*?\Kbar
各部分逻辑说明:
\G锚定匹配位置在上一次匹配结束的位置,确保不会跳过需要排除的foo...bar结构(?:(?!foo[\s\-/]*bar).)*?惰性匹配任意字符,且确保匹配过程中不会出现需要排除的foo + 允许分隔符 + bar结构\K截断之前匹配的内容,只保留最终的bar作为匹配结果
如果所用引擎不支持
\K语法,可以改用捕获组提取结果,写法如下,最终取分组1的内容即可:^(?:.*?(?:foo[\s\-/]*bar)?)*?(bar)
测试用例验证
- 命中匹配的场景:
- 独立
bar - 普通前缀加
bar,例如test bar foo和bar直接连接(无允许分隔符),例如foobarfoo和bar中间的字符不在[\s\-/]范围内,例如fooXbar
- 独立
- 排除匹配的场景:
foo bar(空格分隔)foo-bar(横杠分隔)foo/bar(斜杠分隔)foo --// bar(多个允许的分隔符混合)
内容的提问来源于stack exchange,提问作者Bastien Déchamps
相关产品推荐
相关产品推荐

