Java正则表达式:负向先行断言

36

我试图创建两个正则表达式来匹配URI。这些URI的格式为:/foo/someVariableData/foo/someVariableData/bar/someOtherVariableData

我需要两个正则表达式,每个正则表达式只匹配其中一个。

我最初想出的正则表达式是:/foo/.+/foo/.+/bar/.+

我认为第二个正则表达式没问题,它只匹配第二个字符串。然而,第一个正则表达式会同时匹配两个字符串。因此,我开始尝试使用负向先行断言(negative lookahead)。我设计了正则表达式/foo/.+(?!bar)并设置以下代码进行测试:

public static void main(String[] args) {
    String shouldWork = "/foo/abc123doremi";
    String shouldntWork = "/foo/abc123doremi/bar/def456fasola";
    String regex = "/foo/.+(?!bar)";
    System.out.println("ShouldWork: " + shouldWork.matches(regex));
    System.out.println("ShouldntWork: " + shouldntWork.matches(regex));
}

当然,它们两个都解析为true

有人知道我做错了什么吗?我不一定需要使用负向先行断言,我只需要解决这个问题,而我认为负向先行断言可能是一种方法。

谢谢,

1个回答

64

请尝试

String regex = "/foo/(?!.*bar).+";
或者可能。
String regex = "/foo/(?!.*\\bbar\\b).+";

为了避免在像/foo/baz/crowbars这样的路径上失败,我假设你确实希望该正则表达式匹配。

解释:(不需要Java字符串所需的双反斜杠)

/foo/ # Match "/foo/"
(?!   # Assert that it's impossible to match the following regex here:
 .*   #   any number of characters
 \b   #   followed by a word boundary
 bar  #   followed by "bar"
 \b   #   followed by a word boundary.
)     # End of lookahead assertion
.+    # Match one or more characters

\b 是一个 "单词边界锚点",它匹配字母数字字符和非字母数字字符之间的空白位置(或字符串的开始/结束和字母数字字符之间的位置)。因此,它在 "bar" 中的 b 前或 r 后匹配,但在 "crowbar" 中的 wb 之间不匹配。

提示:可以参考 http://www.regular-expressions.info,这是一个很棒的正则表达式教程。


.* 在负向先行断言表达式 (?!.*bar) 中的位置非常关键,而不是在外面 .*(?!bar)。谢谢。 - Gary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接