我正在编写一个小型java程序来进行一些数据库清理,当它们与某些关键字出现在同一个句子中时,我需要从大文本 block 中提取日期,并且我遇到了一些奇怪的行为想不通。例如,以下正则表达式:
"(?=.*(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”
出现在日期之前。如果我去掉前瞻,字符串就会匹配。谁能看到我做错了什么吗?谢谢!
最佳答案
您似乎忘记了前瞻是零宽度,这意味着正则表达式光标将设置在前瞻开始检查其条件的位置。这意味着部分匹配
+ "(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|...
之前添加 .*?
,让月份存在更远的地方,通过前瞻检查并匹配 (就像到期
之前的地方)。
此外,为了避免多次使用前瞻,请通过在开头添加 ^
使其仅在字符串开始后查找匹配项。
所以你的最终正则表达式可以看起来像
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)";
<小时/>
实际上我不确定你为什么要使用前瞻。不会像
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)";
也做你想做的事吗?
关于java - 正则表达式 Lookahead 未按预期匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24747682/