2011-02-17 167 views
1

在Java中,我无法得到一个正则表达式来表现我想要的方式,并写了这个小JUnit测试来说明问题:Java的正则表达式与前瞻失败

public void testLookahead() throws Exception { 
    Pattern p = Pattern.compile("ABC(?!!)"); 
    assertTrue(p.matcher("ABC").find()); 
    assertTrue(p.matcher("ABCx").find()); 
    assertFalse(p.matcher("ABC!").find()); 
    assertFalse(p.matcher("ABC!x").find()); 
    assertFalse(p.matcher("blah/ABC!/blah").find()); 

    p = Pattern.compile("[A-Z]{3}(?!!)"); 
    assertTrue(p.matcher("ABC").find()); 
    assertTrue(p.matcher("ABCx").find()); 
    assertFalse(p.matcher("ABC!").find()); 
    assertFalse(p.matcher("ABC!x").find()); 
    assertFalse(p.matcher("blah/ABC!/blah").find()); 

    p = Pattern.compile("[A-Z]{3}(?!!)", Pattern.CASE_INSENSITIVE); 
    assertTrue(p.matcher("ABC").find()); 
    assertTrue(p.matcher("ABCx").find()); 
    assertFalse(p.matcher("ABC!").find()); 
    assertFalse(p.matcher("ABC!x").find()); 
    assertFalse(p.matcher("blah/ABC!/blah").find()); //fails, why? 

    p = Pattern.compile("[A-Za-z]{3}(?!!)"); 
    assertTrue(p.matcher("ABC").find()); 
    assertTrue(p.matcher("ABCx").find()); 
    assertFalse(p.matcher("ABC!").find()); 
    assertFalse(p.matcher("ABC!x").find()); 
    assertFalse(p.matcher("blah/ABC!/blah").find()); //fails, why? 
} 

每一行通过除了两个用评论标记。除了模式字符串外,这些分组是相同的。为什么添加不区分大小写会打破匹配器?

回答

1

你的测试失败,因为在这两种情况下,模式[A-Z]{3}(?!!)(与CASE_INSENSITIVE)和[A-Za-z]{3}(?!!)发现"blah/ABC!/blah"至少一个比赛(他们发现bla两次)。

一个简单的测试表明这一点:

Pattern p = Pattern.compile("[A-Z]{3}(?!!)", Pattern.CASE_INSENSITIVE); 
Matcher m = p.matcher("blah/ABC!/blah"); 
while(m.find()) { 
    System.out.println(m.group()); 
} 

打印:

bla 
bla 
+0

DUH!所有的答案都是正确的,而且我自己也没有看到它,所以感到羞耻。这个答案得到了胜利,也告诉我我应该如何在自己身上找到它...... – romacafe 2011-02-17 22:55:35

1

这两个不会抛出错误的值,因为在匹配模式的完整字符串中有子字符串。具体而言,字符串blah与正则表达式(三个字母后面没有感叹号)匹配。区分大小写的正确失败,因为blah不是大写。