正则表达式Lookahead不符合预期

时间:2014-07-14 23:33:28

标签: java regex

我正在写一个小的java程序进行一些数据库清理,当我们需要从大块文本中提取日期时,它们出现在与某些关键字相同的句子中,并且我得到一些奇怪的行为,我想不通。例如,以下正则表达式:

"(?=.*(due|submit|deadline)[^\\d]*)"
+ "(january|february|march|april|may|june|july|august|september|october|november|december)"
+ "\\s*(0?[1-9]|[12][0-9]|3[01])(th|rd|nd|st)*,*\\s*((19|20)\\d\\d)"

不匹配:

“必须在2013年6月19日星期三中午12点之前提交,届时将会被阅读。”

虽然关键字"submit"发生在日期之前。如果我拿出前瞻,字符串匹配。谁能看到我做错了什么?谢谢!

1 个答案:

答案 0 :(得分:1)

似乎你忘记了前瞻是零宽度,这意味着正则表达式光标将被设置在前瞻开始检查其状态的地方。这意味着零件匹配

+ "(january|february|march|april|may|june|july|august|september|october|november|december)"
+ "\\s*(0?[1-9]|[12][0-9]|3[01])(th|rd|nd|st)*,*\\s*((19|20)\\d\\d)";

需要在先行开始检查的地方之后存在。

要解决此问题,您需要在.*?之前添加(january|...,以便通过前瞻和匹配(例如due之前的位置)来检查几个月的位置。

另外,要避免多次使用前瞻,只需在启动后添加^即可在字符串启动后立即查找匹配项。

所以你的最终正则表达式看起来像

    String regex = "^(?=.*(due|submit|deadline)[^\\d]*)"
            + ".*?(january|february|march|april|may|june|july|august|september|october|november|december)"
            + "\\s*(0?[1-9]|[12][0-9]|3[01])(th|rd|nd|st)*,*\\s*((19|20)\\d\\d)";

Look-ahead demo


实际上我不确定你为什么甚至使用预测。不会像

那样
    String regex = "(due|submit|deadline).*?"
            + "(january|february|march|april|may|june|july|august|september|october|november|december)"
            + "\\s*(0?[1-9]|[12][0-9]|3[01])(th|rd|nd|st)*,*\\s*((19|20)\\d\\d)";

也做你想做的事情?

No look-ahead demo