前面我们讲过如何把量词一次附加到一个字符、字符类或者捕获组之后。但是到目前为止,我们还没有详细讨论过捕获组的概念。
捕获组(capturing group)是把多个字符当作一个单元对待的一种方式。通过把字符括在括号内创建捕获组。例如,正则表达式(dog)创建包含字母“d”、“o”和“g”的一个组。输入字符串和捕获组匹配的那一部分将被保存在内存中,以便以后通过反向引用再次使用(见13.7.2节的讨论)。
13.7.1 编号
如Pattern API中所述,按照从左到右的顺序计算捕获组的前括号数目,给捕获组编号。例如,在表达式((A)(B(C)))中,有4个这样的组:
(1) ((A)(B(C)))
(2) (A)
(3) (B(C))
(4) (C)
为了查出表达式中有多少个组,可以对匹配器对象调用groupCount方法。groupCount方法返回一个int,表示匹配器模式中出现的捕获组的数量。在这个例子中,groupCount将返回4,显示这个模式包含4个捕获组。
还有一个特殊的组,组0,它总是代表整个表达式。这个组不包括在groupCount报告的总数内。以(?开头的组是纯粹的非捕获组(non-capturing group),它不捕获文本,也不计入组的总数。(后面的13.9节中将给出非捕获组的例子。)
了解组如何编号非常重要,因为一些Matcher方法接受指定特定捕获组编号的int作为参数:
l public int start(int group)——返回前一个匹配操作期间,给定组捕获的子序列的开始索引。
l public int end(int group)——返回前一个匹配操作期间,给定组捕获的子序列的最后一个字符的索引加1。
l public String group(int group)——返回前一个匹配操作期间,给定组捕获的输入子序列。
13.7.2 反向引用
输入字符串中和捕获组匹配的部分被保存在内存中,以便以后通过反向引用(backreference)再次使用。反向引用在正则表达式中被指定为反斜线(/),后面跟着一个数字,指出要再次使用的组的编号。例如,表达式(/d/d)定义匹配一行中两个数字的一个捕获组,以后可以通过反向引用/1再次使用它。
为了匹配任意两个数字,后面跟着完全相同的两个数字,可以使用(/d/d)/1作为正则表达式:
Enter your regex: (/d/d)/1
Enter input string to search: 1212
I found the text "1212" starting at index 0 and ending at index 4.
如果改动最后两个数字,匹配就会失败:
Enter your regex: (/d/d)/1
Enter input string to search: 1234
No match found.
对于嵌套捕获组,反向引用的工作方式完全相同:指定一个反斜线,后面跟着要再次使用的组的编号。