Java正则表达式中的零长度匹配

Java正则表达式中的零长度匹配,java,regex,Java,Regex,我的代码: 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?”表示字符“a

我的代码:

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?”表示字符“a”的零次或一次出现
Java API说:

  • start()返回上一个匹配的开始索引
  • end()返回最后一个匹配字符后的偏移量
  • group()返回与前一个匹配的输入子序列 匹配。对于具有输入序列s的匹配器m,表达式 m、 group()和s.substring(m.start(),m.end())是等效的。以及 某些模式,例如a*,与空字符串匹配。这种方法 将在模式成功匹配时返回空字符串 输入中的空字符串
我想知道的是:

  • 在哪些情况下,正则表达式引擎遇到零 给定字符的出现-此处为字符“a”
  • 在这种情况下,start()实际返回的值是什么, 匹配器中的end()和group()方法。我已经提到了 JavaAPI说。但我有点不清楚它的实际用途 情况同上

  • 是一个贪婪的量词,因此它将首先尝试匹配1-occurrence,然后再尝试0-occurrence。在你的弦里

  • 它以第一个字符“a”开始,并尝试再次匹配1-occurrence。“a”字符匹配,因此它返回您看到的第一个结果
  • 然后它向前移动并找到一个“b”。“b”字符与regexp 1-occurrence不匹配,因此引擎将回溯并尝试匹配0-occurrence。结果是空字符串匹配-->您将获得第二个结果
  • 然后它移到b的前面,因为在那里不可能有更多的匹配,它会以您的第二个“a”字符重新开始
  • 等等。。。你明白了
  • 这比那要复杂一点,但这是主要思想。当1-occurrence不匹配时,它将尝试使用0-occurrence


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

    反复阅读几个示例可以让您了解
    matcher.find()的功能:

    正则表达式引擎从字符串(即ababa)中提取一个字符,并尝试查找您在字符串中查找的模式是否可以找到。如果模式存在,则(如API所述):

    start()返回起始索引, 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[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
    

    +谢谢你的解释。您是否指出“a?”在语义上等同于搜索字符串“a”或“”?那么你能解释一下为什么在源字符串的末尾总是有一个零长度的字符吗?例如:对于“aaaa”,它在结尾处也给出了4[]4,表示模式“a?”?+1提到了贪婪量词行为的解释。但是最后一个呢?为什么总是在每个字符串末尾加0个出现呢?让我们用字符串“A”来做一个简单的例子。引擎在0中启动并尝试匹配“a”-->成功,因此第一次匹配并将forwars移动到位置1-->中的位置1-->时,它会尝试1-发生匹配-->失败,因为已到达字符串结尾。它仍然可以进行0匹配-->成功。然后它向前移动-->字符串结束-->匹配结束非常接近纪尧姆。但在成功匹配“a”之后,为什么和如何继续前进。没有更多的索引;没有更多的角色。是吗?@Narmal我相信一旦到达大于字符串长度的位置,引擎就会停止。例如,对于字符串“a”(长度为1),位置0和1有效,位置2大于长度,这将触发匹配结束