java REGEXP:捕获组后不跟随

cvxl0en2  于 2023-05-05  发布在  Java
关注(0)|答案(3)|浏览(81)

我需要匹配以下语句:

Hi there John
Hi there John Doe (jdo)

不匹配这些:

Hi there John Doe is here 
Hi there John is here

所以我想这个regexp可以工作:

^Hi there (.*)(?! is here)$

但是它没有-我不确定为什么-我相信这可能是由捕获组(.*)引起的,所以我想也许让 * 操作符懒惰会解决这个问题...但是不行。这个regexp也不工作:

^Hi there (.*?)(?! is here)$

有人能给我指出解决方案的方向吗?

溶液

要检索结尾没有**is here的句子**(如Hi there John Doe (the second)),您应该使用(author @Thorbear):

^Hi there (.*$)(?<! is here)

对于中间包含一些数据的句子(如Hi there John Doe (the second) is hereJohn Doe(第二个) 是所需的数据),简单的分组就足够了:

^Hi there (.*?) is here$

.

╔══════════════════════════════════════════╗
           ║▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒║
           ║▒▒▒Everyone, thank you for your replies▒▒▒║
           ║▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒║
           ╚══════════════════════════════════════════╝
uwopmtnx

uwopmtnx1#

.*将找到匹配,而不管是否贪婪,因为在该行的末尾,没有随后的is here(自然地)。
解决这个问题的一个方法是使用lookbehind(从行尾检查,如果过去的几个字符与is here匹配)。
^Hi there (.*)(?<! is here)$

    • 编辑**

正如Alan Moore所建议的,进一步将模式更改为^Hi there (.*$)(?<! is here)将提高模式的性能,因为捕获组将在尝试向后查找之前吞噬字符串的其余部分,从而节省了不必要的回溯。

k3fezbri

k3fezbri2#

从您的示例中还不完全清楚您是否希望防止“is here”在任何地方出现或仅在行尾出现。如果它不应该发生在任何地方,请尝试以下操作:

^Hi there ((?! is here).)*$

在每个字符之前,它检查下一个字符是否不是“is here”。
或者,如果你只想在它出现在一行的最后时排除它,你可以像Thorbear建议的那样使用负向后看:

^Hi there (.*)(?<! is here)$

您完全正确地解释了为什么您的表达式与所有输入行匹配。.*匹配了所有内容,并且(?! is here)$的预测总是为真,因为“is here”永远不会在行尾之后出现(因为那里什么都没有)。

toiithl6

toiithl63#

你不需要用正则表达式来解决你的问题,你只需要使用正则表达式来找出非预期的正则表达式是否匹配。当然,如果你已经知道这一点,只是想了解一下lookaheads/lookbehinds,你可以放弃这个答案的其余部分。
如果你使用你不希望输入字符串匹配的正则表达式:

badregex = (Hi there (.*)(is here))

这将给予你一个匹配

Hi there, John is here

因此,您可以将逻辑放在应用程序级别,它应该在的地方(regex中的逻辑是一件糟糕的事情)。一点伪代码(我现在可以写出Java,但你已经明白了)

if (badregex.exactMatch(your_str))
   discardString();
   return;
if (goodregex.exactMatch(your_str))
   doStuff(your_str);

相关问题