JAVA正则表达式高级用法(分组与捕获)

正则表达式在字符串处理中常常使用,关于正则简单的用法相信有一点程序基础的人都懂得一些,这里就不介绍简单基础了。这里主要讲解一下在JAVA中实现了的正则的高级用法-分组与捕获。
对于要重复单个字符,很是简单,直接在字符后卖弄加上限定符便可,例如 a+ 表示匹配1个或一个以上的a,a?表示匹配0个或1个a。这些限定符以下所示:
html

X ?               X ,一次或一次也没有
X *               X ,零次或屡次
X +               X ,一次或屡次
X { n }           X ,刚好 n 次
X { n ,}          X ,至少 n 次
X { n , m }       X ,至少 n 次,可是不超过 m 次


可是咱们若是要对多个字符进行重复怎么办呢?此时咱们就要用到分组,咱们可使用小括号"()"来指定要重复的子表达式,而后对这个子表达式进行重复,例如:(abc)? 表示0个或1个abc 这里一 个括号的表达式就表示一个分组 。
分组能够分为两种形式,捕获组和非捕获组。
java

捕获组  
捕获组能够经过从左到右计算其开括号来编号 。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:
正则表达式

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

组零始终表明整个表达式之因此这样命名捕获组是由于在匹配中,保存了与这些组匹配的输入序列的每一个子序列。捕获的子序列稍后能够经过 Back 引用 在表达式中使用,也能够在匹配操做完成后从匹配器检索。
Back 引用 是说在后面的表达式中咱们可使用组的编号来引用前面的表达式所捕获到的文本序列(是文本不是正则) 。
例如 ([" ']).* /1   其中使用了分组,/1就是对引号这个分组的引用,它匹配包含在两个引号或者两个单引号中的全部字符串,如,"abc" 或 " ' " 或 ' " '  ,可是请注意,它并不会对" a'或者 'a"匹配。缘由上面已经说明,Back引用只是引用文本而不是表达式。

非捕获组  
以 (?) 开头的组是纯的非捕获 组,它不捕获文本 ,也不针对组合计进行计数。就是说,若是小括号中以?号开头,那么这个分组就不会捕获文本,固然也不会有组的编号,所以也不存在Back 引用。
在Java中,支持的非捕获组,有以下几种:
测试

(?= X )          X ,经过零宽度的正 lookahead
(?! X )          X ,经过零宽度的负 lookahead
(?<= X )         X ,经过零宽度的正 lookbehind
(?<! X )         X ,经过零宽度的负 lookbehind

这四个非捕获组用于匹配表达式X,可是不包含表达式的文本。

(?=X )     零宽度正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,/w+(?=/d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。
(?!X)     零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,/w+(?!/d) 与后不跟数字的单词匹配,而不与该数字匹配 。
(?<=X)     零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。
(?<!X)     零宽度负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配

举例:
上面都是理论性的介绍,这里就使用一些例子来讲明一下问题:
  一、测试匹配性   (?<!4)56(?=9) 这里的含义就是匹配后面的文本56前面不能是4,后面必须是9组成。所以,能够匹配以下文本 5569  ,与4569不匹配。
   2 、提取字符串   提取 da12bka3434bdca4343bdca234bm   提取包含在字符a和b之间的数字,可是这个a以前的字符不能是c,b后面的字符必须是d才能提取。
   例如这里就只有3434这个数字知足要求。那么咱们怎么提取呢?
    首先咱们写出提取这个字符串的表达式: (?<!c)a(/d+)bd  这里就只有一个捕获组(/d+)
 JAVA代码片断以下:
spa

    Pattern p = Pattern.compile( "(?<!c)a(//d+)bd " );
    Matcher m = p.matcher( "da12bka3434bdca4343bdca234bm" );
    while (m.find()){
        System.out.println(m.group( 1 )); //咱们只要捕获组1的数字便可。结果 3434
        System.out.println(m.group(0)); // 0组是整个表达式,看这里,并无提炼出(?<!c)的字符 。结果 a3434bd
    }

    能够看到,非捕获组,最后是不会返回结果的,由于它自己并不捕获文本。
code