5

我需要匹配以下语句:

Hi there John
Hi there John Doe (jdo)

不匹配这些:

Hi there John Doe is here 
Hi there John is here

所以我认为这个正则表达式会起作用:

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

但它没有 - 我不知道为什么 - 我相信这可能是由捕获组(。*)引起的,所以我认为也许让 * 运算符变得懒惰会解决问题......但不是。这个正则表达式也不起作用:

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

谁能指出我的解决方案方向?

解决方案

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

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

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

^Hi there (.*?) is here$

.

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

3 回答 3

4

无论是否贪心,.*都会找到匹配项,因为在行尾,没有跟随is here(自然)。

对此的解决方案可能是改用lookbehind(从行尾检查,如果过去的几个字符与 匹配is here)。

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

编辑

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

于 2012-08-01T14:39:22.863 回答
3

如果您想防止“在这里”出现在任何地方或仅在一行的末尾,您的示例并不完全清楚。如果它不应该发生在任何地方,试试这个:

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

重新提琴示例

在每个字符之前,它会检查下一个字符是否不是“在这里”。

或者,如果您只想在它出现在一行的末尾时将其排除,您可以按照 Thorbear 的建议使用否定的lookbehind:

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

您的表达式与所有输入行匹配的原因是绝对正确的。.*匹配所有内容,并且前瞻(?! is here)$将始终为真,因为“在此处”永远不会在行尾之后出现(因为那里什么都不会出现)。

于 2012-08-01T14:35:26.050 回答
1

您不需要用正则表达式解决您的问题,您只需要使用正则表达式来找出非预期的正则表达式是否匹配。当然,如果您已经知道这一点并且只是想了解前瞻/后瞻,您可以放弃此答案的其余部分。

如果您使用正则表达式,您希望您的输入字符串匹配:

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

这会给你一个匹配

Hi there, John is here

所以你可以把逻辑放在应用程序级别,它应该在哪里(正则表达式中的逻辑是一件坏事)。一点伪代码(我现在 cba 写出 Java,但你明白了)

if (badregex.exactMatch(your_str))
   discardString();
   return;
if (goodregex.exactMatch(your_str))
   doStuff(your_str);
于 2012-08-01T14:39:44.657 回答