正则表达式负前瞻未达预期匹配效果,请求排查问题
正则排除带时间的交易记录问题修复
我看了你的问题,你想排除那段带02:45:28 PM时间戳的交易记录,但现在两段都被匹配到了,问题出在你负前瞻的写法和位置上,咱们一步步拆解:
你的原始内容与正则
待匹配字符串:
6015603 06/12/2017 06/12/2017 02:45:28 PM - BIL/001347764403/LOAN/NSP CR 20,000.00 8,381.002 S 6156702 06/12/2017 06/12/2017 6015603 06/12/2017 06/12/2017 - BIL/001347764403/LOAN/NSP CR 20,000.00 8,381.002 S 6156702 06/12/2017 06/12/2017
你使用的正则:
[0-9]+\s+[0-9]{2}[\/][0-9]{2}[\/][0-9]{4}\s+[0-9]{2}[\/][0-9]{2}[\/][0-9]{4}\s*(?![0-9]{2}[:][0-9]{2}[:][0-9]{2}\s*(AM|PM)).*?(?=([0-9]+\s*[0-9]{2}[\/][0-9]{2}[\/][0-9]{4}+\s+[0-9]{2}[\/][0-9]{2}[\/][0-9]{4})|\\Z)
问题根源
你的负前瞻(?![0-9]{2}[:][0-9]{2}[:][0-9]{2}\s*(AM|PM))放在了\s*之后,这给了正则回溯的漏洞:
- 正则先匹配完第三个日期,接着尝试匹配时间前面的所有空格
- 此时检查负前瞻,发现空格后是时间格式,不符合排除条件,这个分支失败
- 正则会自动回溯,让
\s*匹配0个空格,此时检查第三个日期后的第一个字符(就是空格),它不匹配时间格式的开头[0-9]{2},负前瞻就会错误判定“后面没有时间”,最终把第一段也匹配上了!
修复方案
调整负前瞻的逻辑,确保第三个日期之后,不管有多少空格,只要跟着时间格式就排除,同时避免回溯漏洞。修改后的正则如下:
[0-9]+\s+[0-9]{2}/[0-9]{2}/[0-9]{4}\s+[0-9]{2}/[0-9]{2}/[0-9]{4}(?!\s*[0-9]{2}:[0-9]{2}:[0-9]{2}\s*(AM|PM)).*?(?=\s*[0-9]+\s+[0-9]{2}/[0-9]{2}/[0-9]{4}\s+[0-9]{2}/[0-9]{2}/[0-9]{4}|$)
关键修改点
- 负前瞻改为
(?!\s*[0-9]{2}:[0-9]{2}:[0-9]{2}\s*(AM|PM)):在时间模式前加\s*,不管有多少空格,只要后续是时间就排除 - 把负前瞻直接跟在第三个日期后面,移除原本的
\s*,避免正则回溯到匹配0个空格的情况 - 优化结尾断言,将
\\Z改为更通用的$,同时在记录开头前加\s*,确保匹配下一个记录时忽略多余空格
这样修改后,带时间戳的第一段会被正确排除,只会匹配第二段无时间的交易记录。
内容的提问来源于stack exchange,提问作者manish
相关产品推荐
相关产品推荐

