2012-03-28 50 views
7

我的代码:零长度在Java中的正则表达式匹配

Pattern pattern = Pattern.compile("a?"); 
Matcher matcher = pattern.matcher("ababa"); 
while(matcher.find()){ 
    System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end()); 
} 

输出:

0[a]1 
1[]1 
2[a]3 
3[]3 
4[a]5 
5[]5 

我知道什么:

  • “?一”代表字符'a'的零次或一次出现。

的Java API说:

  • matcher.start()返回在以前匹配的初始索引。
  • matcher.end()返回匹配的最后一个字符后的偏移量。
  • matcher.group()返回匹配前一个 匹配的输入子序列。对于输入序列为s的匹配器m,表达式 m.group()和s.substring(m.start(),m.end())是等价的。对于 ,某些模式(例如a *)与空字符串匹配。当模式成功匹配 输入中的空字符串时,此方法 将返回空字符串。

我想知道的:

  1. 在哪些情况下不会对正则表达式引擎遇到一个零 发生的指定字符(S)的 - 这里是字符 'A'。
  2. 在那些情况下,匹配器中的start(), end()和group()方法实际返回的值是什么。我已经提到了java API所说的 。但就上述情况而言,我还不太清楚。

回答

10

?是一个贪婪的量词,因此它会先尝试匹配1次出现,然后再尝试0次出现。在你的字符串中,

  1. 它从第一个字符'a'开始并尝试再次匹配1次发生。 'a'字符匹配,所以它返回你看到的第一个结果
  2. 然后它向前移动并找到'b'。 'b'字符与您的正则表达式1出现不匹配,所以引擎回溯并尝试匹配0次出现。结果是空字符串匹配 - >你得到第二个结果。
  3. 然后它在b之前移动,因为在那里没有更多的匹配可能,并且它会再次以第二个'a'字符开始。
  4. 等等......你明白了吧...

这是比这更复杂一点,但是这是主要的想法。当1次出现不匹配时,它会尝试0次出现。

至于开始,结束和组的值,它们将是匹配开始的位置,结束位置和组匹配的位置,因此在字符串的第一个0匹配匹配中,会得到1,1和emtpy字符串。我不确定这真的会回答你的问题。

+0

+1提的贪婪量词的行为的解释。但是最后5 [5]呢?为什么它总是在每个字符串的末尾添加0出现? – namalfernandolk 2012-03-28 12:50:43

+0

让我们用字符串“a”来举一个简单的例子。引擎从0开始,并尝试匹配'a' - >成功,所以首先匹配并将forwars移动到位置1的位置1,它尝试1匹配匹配 - >失败,因为到达字符串末尾。它仍然可以进行0次匹配 - >成功。然后它向前移动 - >字符串结尾 - >匹配结束 – 2012-03-28 12:55:22

+0

非常感谢Guillaume。但是在成功匹配'a'之后为什么以及如何向前发展。没有更多的索引;并没有更多的字符。不是吗? – namalfernandolk 2012-03-28 13:11:26

3

遍历几个例子将清除出matcher.find()运作给你:

正则表达式引擎呈现一个字符的字符串(即巴),并试图找到,如果你正在寻找在字符串模式无法找到或不。如果该模式存在,则(如API所述):

matcher.start()返回起始索引, matcher.end()返回匹配的最后一个字符后的偏移量。

如果匹配不存在。然后start()和end()返回相同的索引,这符合匹配的长度为零。

往下看下面的例子:

 // Searching for string either "a" or "" 
     Pattern pattern = Pattern.compile("a?"); 
     Matcher matcher = pattern.matcher("abaabbbb"); 
     while(matcher.find()){ 
      System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end()); 
     } 

输出:

0[a]1 
    1[]1 
    2[a]3 
    3[a]4 
    4[]4 
    5[]5 
    6[]6 
    7[]7 
    8[]8 


     // Searching for string either "aa" or "a" 
     Pattern pattern = Pattern.compile("aa?"); 
    Matcher matcher = pattern.matcher("abaabbbb"); 
    while(matcher.find()){ 
     System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end()); 
    } 

输出:

0[a]1 
2[aa]4 
+0

+1为好的解释。你是否指出“一个?”是equalant(语义上)搜索字符串“a”或“”?那么你能解释为什么总是在源字符串的末尾使用零长度字符?例如:对于“aaaa”,它最后给出了4 [] 4的模式“a?”。 ? – namalfernandolk 2012-03-28 12:41:45