java正则类Matcher详解
一、捕获组的概念
捕获组可以通过从左到右计算其开括号来编号,编号是从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()
- 返回由以前匹配(此匹配是匹配整个正则表达式,也即组0。看“组和捕获”)操作所匹配的输入子序列。
对于具有输入序列 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