java - 正则表达式 Lookahead 未按预期匹配

标签 java regex

我正在编写一个小型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)";

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

关于java - 正则表达式 Lookahead 未按预期匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24747682/

相关文章:

javascript - 量词不起作用

Java正则表达式文件名不重复

java - 在 B+ 树中寻找中位数

java - String.replaceAll() 和 [\d]* 在字符之间追加替换字符串,为什么?

java - java中的对象创建语句到底是什么意思?

java - 提取以美元符号为前缀的大括号内占位符的内容

仅当行不包含另一个字符串时,正则表达式才匹配一个字符串

regex - 命名和未命名的 PCRE 捕获组如何交互?

java - Java Blob 存储的 API/接口(interface)

java - 从 XML 检索数据