程序员的日常记忆

正则表达式分组与捕获

2019-06-27  本文已影响0人  一名程序猿

分组

分组的引入
对于要重复单个字符,非常简单,直接在字符后卖弄加上限定符即可,例如 a+ 表示匹配1个或一个以上的a,a?表示匹配0个或1个a。这些限定符如下所示:

X ? X ,一次或一次也没有
X * X ,零次或多次
X + X ,一次或多次
X { n } X ,恰好 n 次
X { n ,} X ,至少 n 次
X { n , m } X ,至少 n 次,但是不超过 m 次
但是我们如果要对多个字符进行重复怎么办呢?此时我们就要用到分组,我们可以使用小括号()来指定要重复的子表达式,然后对这个子表达式进行重复,例如:(abc)? 表示0个或1个abc 这里一 个括号的表达式就表示一个分组 。分组可以分为两种形式,捕获组和非捕获组。

捕获组

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

0 (A)(B(C))
1 (A)
2 (B(C))
3 (C)
组0始终代表整个表达式

之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用(反向引用) 在表达式中使用,也可以在匹配操作完成后从匹配器检索。

Back 引用 是说在后面的表达式中我们可以使用组的编号来引用前面的表达式所捕获到的文本序列。注意:反向引用,引用的是前面捕获组中的文本而不是正则,也就是说反向引用处匹配的文本应和前面捕获组中的文本相同,这一点很重要。

【例】(["']).*\1

其中使用了分组,\1就是对引号这个分组的引用,它匹配包含在两个引号或者两个单引号中的所有字符串,如,”abc” 或 ” ’ ” 或 ’ ” ’ ,但是请注意,它并不会对” a’或者 ‘a”匹配。原因上面已经说明,Back引用只是引用文本而不是表达式。

非捕获组
以 (?) 开头的组是纯的非捕获 组,它不捕获文本 ,也不针对组合计进行计数。就是说,如果小括号中以?号开头,那么这个分组就不会捕获文本,当然也不会有组的编号,因此也不存在Back 引用。

我们通过捕获组就能够得到我们想要匹配的内容了,那为什么还要有非捕获组呢?原因是捕获组捕获的内容是被存储在内存中,可供以后使用,比如反向引用就是引用的内存中存储的捕获组中捕获的内容。而非捕获组则不会捕获文本,也不会将它匹配到的内容单独分组来放到内存中。所以,使用非捕获组较使用捕获组更节省内存。在实际情况中我们要酌情选用。

分组使用

对正则表达式分组之后,就额可以通过Matcher 对象的group方法进行获取分组后匹配的值。

代码示例

package com.ysh.micro.client.controller;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestServiceUseController {
  public static void main(String[] args) {
      String s = "天a11.77天";
      Pattern p = Pattern.compile("(\\d+(\\.\\d+)?)天");
      Matcher m = p.matcher(s);
      //System.out.println(m.find());
      System.out.println(m);
      if(m.find()) {
          System.out.println(m.group(1));
      }
  }
}
0代码代表整个正则表达式的结果,数组下标依次获取每个小分组获取的结果。

方法介绍

find:是否找到匹配
group:获取分组匹配的值
replaceAll:将匹配的值替换

上一篇 下一篇

猜你喜欢

热点阅读