【问题标题】:Regex negative look ahead not giving desired result正则表达式负面展望没有给出预期的结果
【发布时间】:2018-05-10 03:40:28
【问题描述】:

我有两个字符串,如下所示:

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))

但是当我运行模式匹配时,两个字符串都匹配。我希望忽略第一个字符串。我在做什么错了?

【问题讨论】:

  • 您的语言是否转义了反斜杠?你想要一个字符串文字。或者每次你想要一个正则表达式时使用双反斜杠
  • 好吧,我正在使用 java。我只是让它在一般的正则表达式中呈现出来,而不管任何语言。在我的代码中,我使用了转义字符,例如 \s+ 显然是 \\s+

标签: regex pattern-matching negative-lookahead


【解决方案1】:

我得到了解决方案,我没有将 \s* 包括在负面展望中。包含它后它可以正常工作。

错误的是:

\s*(?![0-9]{2}[:][0-9]{2}[:][0-9]{2}\s*(AM|PM))

正确的是:

(?!\s*[0-9]{2}[:][0-9]{2}[:][0-9]{2}\s*(AM|PM))

我从以下线程中获取了答案参考: regex: Why this negative lookahead doesn't work?

【讨论】:

【解决方案2】:

您可以在匹配第一个日期后添加(?!.*?\d{2}:\d{2}:\d{2}\s*[AP]M) 否定前瞻:

^\d+\s+\d{2}/\d{2}/\d{4}\s+\d{2}/\d{2}/\d{4}(?!.*?\d{2}:\d{2}:\d{2}\s*[AP]M).*?(?=(\d+\s*\d{2}/\d{2}/\d{4}\s+\d{2}/\d{2}/\d{4})|$)
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

请参阅regex demo

如果在第一个日期和任何 0+ 个字符之后尽可能少地存在与 \d{2}:\d{2}:\d{2}\s*[AP]M 模式匹配的时间子字符串,则前瞻将完全失败。

我还添加了字符串/行的开头^ 锚点,将所有[0-9] 替换为\d(它更短),[\/]/(Java 中的正则表达式不使用正则表达式分隔符,因此没有需要转义/,这不是一个特殊的正则表达式元字符),将(AM|PM)缩小为[AP]M以减少分组开销,并将\Z替换为$,但如果你的意思是字符串的结尾而不是一行,你可以使用你的\Z 锚。

请注意,在 Java 中,您需要对上述字符串中的每个反斜杠进行转义。

【讨论】:

  • 感谢 Wiktor,您的建议很有价值。我认为这些将使我的正则表达式编译更快。 :)
  • @manish 很高兴它对你有用。如果我的回答对您有帮助,也请考虑投票(请参阅How to upvote on Stack Overflow?)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 2016-10-10
  • 1970-01-01
相关资源
最近更新 更多