一、捕获组的概念

捕获组可以通过从左到右计算其开括号来编号,编号是从1 开始的。例如,在表达式 ((A)(B(C)))

1    ((A)(B(C)))2    (A)3    (B(C))4    (C)

组零始终代表整个表达式。 以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。

与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串"aba" 与表达式(a(b)?)+ 相匹配,会将第二组设置为 "b"。在每个匹配的开头,所有捕获的输入都会被丢弃。

 

二、Matcher详解



public boolean find()



此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。

如果匹配成功,则可以通过 start、end 和 group



返回:

true。

public String group()


对于具有输入序列 s 的匹配器 m,表达式 m.group() 和 s.substring(m.start(), m.end())

注意,某些模式(例如,a*)匹配空字符串。当模式成功匹配输入中的空字符串时,此方法将返回空字符串。



指定者:

接口 MatchResult 中的

group


返回:

以前匹配操作所匹配的字符串形式的子序列(可能为空)。 抛出:

IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。




public int start()




指定者:

接口 MatchResult 中的

start


返回:

第一个匹配字符的索引。 抛出:

IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。




public int end()




指定者:

接口 MatchResult 中的

end


返回:

最后匹配字符之后的偏移量。 抛出:

IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。


以上group()、start()、end()这三个不带参数方法是相对应的。group()方法返回的是字符串中一次与整个正则表达式匹配的子字符串,而start()返回的是此次匹配的子字符串在整个字符串中的开始索引,end()方法返回的是此次匹配的子字符串的最后一个字符在整个字符串中的索引(也即匹配的子字符之后的偏移量)。


------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 



public String group(int group)


对于匹配器 m、输入序列 s 和组索引 g,表达式 m.group(g) 和s.substring(m.start(g), m.end(g))

捕获组是从 1 开始从左到右的索引。组零表示整个模式,因此表达式 m.group(0) 等效于 m.group()。

如果该匹配成功了,但指定组未能匹配输入序列的任何部分,则返回 null。注意,某些组(例如,(a*))匹配空字符串。当这些的组成功匹配输入中的空字符串时,此方法将返回空字符串。



指定者:

接口 MatchResult 中的

group


参数:

group - 此匹配器模式中捕获组的索引。

返回:

null。 抛出:

IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。

IndexOutOfBoundsException - 如果在给定索引的模式中不存在捕获组。




public int start(int group)



捕获组是从 1 开始从左到右的索引。组零表示整个模式,因此表达式 m.start(0) 等效于m.start()。



指定者:

接口 MatchResult 中的

start


参数:

group - 此匹配器模式中捕获组的索引。

返回:

-1。 抛出:

IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。

IndexOutOfBoundsException - 如果在给定索引的模式中不存在捕获组。


 



public int end(int group)



捕获组是从 1 开始从左到右的索引。组零表示整个模式,因此表达式 m.end(0) 等效于m.end()。


指定者:

接口 MatchResult 中的

end


参数:

group - 此匹配器模式中捕获组的索引。

返回:

-1。 抛出:

IllegalStateException - 如果没有尝试任何匹配,或者以前的匹配操作失败。

IndexOutOfBoundsException - 如果在给定索引的模式中不存在捕获组。


以上group(int group)、start(int group)、end(int group)这三个带有参数的方法也是相对应的。group(int group)方法返回的是一次与正则表达式参数group指定的组匹配的子字符串,而start(int group))返回的是与参数group指定的(正则表达式捕获)组匹配的子字符串在整个字符串中的开始索引,end()int group方法返回的是与参数group指定的(正则表达式捕获)组匹配的子字符串的最后一个字符在整个字符串中的索引(也即匹配的子字符之后的偏移量)。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 



public boolean find(int start)



如果匹配成功,则可通过 start、end 和 group 方法获取更多信息,而 find() 方法的后续调用将从此匹配操作未匹配的第一个字符开始。



返回:

true。 抛出:

IndexOutOfBoundsException - 如果开始点小于零或大于输入序列的长度。


public int groupCount()



根据惯例,零组表示整个模式。它不包括在此计数中。

任何小于等于此方法返回值的非负整数保证是此匹配器的有效组索引。



指定者:

接口 MatchResult 中的

groupCount


返回:

此匹配器模式中的捕获组数。

可以这样理解:group(0)对应的是整个正则表达式匹配部分,group(1)~group(groupCount)则是小括号内匹配部分。


测试代码

public class TestMatcher{
/**
   * 正则的捕获组测试
   */
  public static void testMatcherGroup2(){
   String  a = "圈子abcddd dfasdabc aabbbcd搜狐来了-=dfd aadbbbababbcdddd";
   String regex = "(a(b)?)+"; // 有两个组:a(b)? 和 b
     
   Matcher m = Pattern.compile(regex).matcher(a);
   List<String> groupAllList = new ArrayList<String>();
   List<String> groupZeroList = new ArrayList<String>();
   List<String> groupOneList = new ArrayList<String>();
   List<String> groupTwoList = new ArrayList<String>();
   while(m.find()){
    groupAllList.add(m.group());
    groupZeroList.add(m.group(0));
    groupOneList.add(m.group(1));
    groupTwoList.add(m.group(2));
   }
   System.out.println("groupAllList=" + groupAllList);
   System.out.println("groupZeroList=" + groupZeroList);
   System.out.println("groupOneList=" + groupOneList);
   System.out.println("groupTwoList=" + groupTwoList);
   
   System.out.println(m.groupCount());   int index = a.indexOf("-=");
    if(m.find(index)){
     System.out.println("------" +m.group(0));
    }}

public static void main(String []args){
      testMatcherGroup2();
     } 
  
 
}


输出结果如下:

groupAllList=[ab, a, ab, aab, aa, abab]
groupZeroList=[ab, a, ab, aab, aa, abab]
groupOneList=[ab, a, ab, ab, a, ab]
groupTwoList=[b, null, b, b, null, b]
2
------aa