正则表达式(?=\d)\w(?=\d)匹配异常求助:为何结果是12和45而非2?
正则匹配逻辑纠正
你的核心错误是搞反了**正向预查(前向肯定断言)**的方向:(?=\d)是检查「当前位置的右侧紧跟数字」,而不是匹配「左侧的数字并忽略」。
先拆解你写的正则(?=\d)\w(?=\d)的匹配逻辑:
(?=\d):定位到一个位置,要求这个位置右边第一个字符是数字\w:匹配这个位置右侧的那个字符(也就是刚才断言的数字)(?=\d):匹配完\w后,新位置的右边必须还是数字
放到字符串123abc456里逐个验证:
- 位置0(
1左边):右边是1(数字),满足第一个断言;\w匹配1,此时位置移到1右边,右边是2(数字),满足第二个断言 → 匹配1 - 位置1(
2左边):右边是2(数字),满足第一个断言;\w匹配2,位置移到2右边,右边是3(数字),满足第二个断言 → 匹配2 - 位置2(
3左边):右边是3(数字),满足第一个断言;\w匹配3,位置移到3右边,右边是a(非数字),不满足第二个断言 → 不匹配 - 位置3-5(
a/b/c左边):右边是字母,不满足第一个断言 → 直接跳过 - 位置6(
4左边):右边是4(数字),满足第一个断言;\w匹配4,位置移到4右边,右边是5(数字),满足第二个断言 → 匹配4 - 位置7(
5左边):右边是5(数字),满足第一个断言;\w匹配5,位置移到5右边,右边是6(数字),满足第二个断言 → 匹配5
所以正确的匹配结果应该是1、2、4、5,你看到的12和45应该是把连续的匹配项误当成了单个结果。
如果你想匹配「被两个数字夹在中间的字符」(比如2),要用反向预查(后向断言):
正确正则是(?<=\d)\w(?=\d),逻辑是:
(?<=\d):检查当前位置左侧是数字(零宽度,不消耗字符)\w:匹配中间的目标字符(?=\d):检查当前位置右侧是数字
这个正则会在123abc456中匹配2和5,符合你最初的预期。
内容的提问来源于stack exchange,提问作者MathMan
相关产品推荐
相关产品推荐

