Java正则匹配#包裹内容:replaceFirst替换异常求助
解决String.replaceFirst匹配范围过大导致替换错误的问题
我完全懂你遇到的坑——你用replaceFirst的时候,正则里的.*是贪婪模式,会从第一个#一路匹配到最后一个#,直接把两个动态表达式都包含进去了,所以第一次替换就把后半段的内容也给覆盖了,结果自然不对。
错误原因分析
你的正则表达式#(date)\\|(.*)\\|(.*)#中,.*是贪婪匹配,它会尽可能匹配最多的字符。所以当第一个#被匹配到后,它会跳过中间的#,直接匹配到整个字符串的最后一个#,导致第一次替换就把#date|Date debut|dd/MM/yyyy# 00:00:00','DD/MM/YYYY HH24:MI:SS') and update_date <= to_timestamp('#date|Date fin|dd/MM/yyyy#这一大段都当成了匹配内容,替换后只剩后面的尾巴。
两种可行的解决方案
方案1:改用非贪婪匹配模式
把正则里的.*换成.*?,?会让匹配变成非贪婪模式,匹配到下一个#就停止:
String content = "select * from queries where update_date >= to_timestamp('#date|Date debut|dd/MM/yyyy# 00:00:00','DD/MM/YYYY HH24:MI:SS') and update_date <= to_timestamp('#date|Date fin|dd/MM/yyyy# 23:59:59','DD/MM/YYYY HH24:MI:SS')"; String begin = "28/05/2018"; String end = "29/05/2018"; content = content.replaceFirst("#(date)\\|(.*?)\\|(.*?)#", begin); content = content.replaceFirst("#(date)\\|(.*?)\\|(.*?)#", end);
方案2:匹配除#外的所有字符
用[^#]*代替.*,这样明确只匹配不包含#的字符,从根本上避免跨#匹配:
content = content.replaceFirst("#(date)\\|([^#]*)\\|([^#]*)#", begin); content = content.replaceFirst("#(date)\\|([^#]*)\\|([^#]*)#", end);
正确结果
用上面任意一种方案,最终都会得到你想要的字符串:
select * from queries where update_date >= to_timestamp('28/05/2018 00:00:00','DD/MM/YYYY HH24:MI:SS') and update_date <= to_timestamp('29/05/2018 23:59:59','DD/MM/YYYY HH24:MI:SS')
内容的提问来源于stack exchange,提问作者Lexahen
相关产品推荐
相关产品推荐

