正则表达式如何实现仅匹配每行等号左侧的所有点号
解决方案
完全可以通过后视(Lookbehind)断言实现该需求,不需要扫描整行内容。
核心逻辑
每行仅存在一个作为左右分隔符的=:所有在=左侧的点,从该点位置往行首方向扫描不会碰到分隔符=;所有在=右侧的点,往行首方向扫描必然会碰到分隔符=。基于这个特征,用负向无限宽度后视断言即可过滤掉=右侧的点,仅匹配左侧的点。
正则写法(后视断言版本)
\.(?<!^[^=]*=)
规则说明
\.:匹配目标点号(?<!^[^=]*=):负向后视断言,要求当前匹配位置的左侧(行首到点号前的内容)不能匹配「行首 + 任意数量非=字符 +=」的模式,即点号位置还未经过分隔符=,属于左侧区域
适用引擎
该写法依赖正则引擎对变长(无限宽度)后视断言的支持,兼容以下环境:
- .NET 全版本
- PCRE2、Java 9+
- JavaScript ES2018 及以上版本
- Python 3.10 及以上版本
兼容写法(不依赖变长后视)
如果运行环境不支持变长后视,可以用前视断言实现同等效果,兼容性更强,同样不会扫描=右侧的冗余内容:
\.(?=[^=]*=)
逻辑为:匹配点号时,确认点号右侧到行尾之间存在分隔符=,且点号和=之间没有其他=,即点号属于左侧区域。
匹配效果验证
针对给出的3行测试样例,上述两个正则都只会匹配=左侧key部分的点号:
- 第一行匹配3个点(
key.other.this.sample中的3个点),不会匹配右侧text.里的点 - 第二行匹配5个点(
key.other.this.sample.with.more中的5个点),不会匹配右侧www.sample.com域名里的点 - 第三行匹配5个点,不会被换行符
\n干扰
原有正则的问题
之前写的正则用了.*(?<=(=))结构,会把点号到行尾的所有内容都纳入匹配扫描范围,不仅性能差,在右侧内容出现符合负向前视规则的点号时还会出现误匹配。
内容的提问来源于stack exchange,提问作者Marco Schliesser
相关产品推荐
相关产品推荐

