本篇将继续介绍Java正则表达式的内容, 相关组件以及API方法。
相关组件与API
在Java中,与正则有关的组件有两个:
1. Pattern
1
说明:
最常用的就是静态方法 public static Pattern compile(String regex) 返回一个Pattern对象,然后调用public Matcher matcher(CharSequence input)方法,返回Matcher对象
2. Matcher
1
数据结构说明与正则分组
数据结构
上面介绍Matcher的API,很多方法看得人迷迷糊糊,什么头指针,尾指针,上一次匹配,这些都是什么意思? 为了说明这个问题,需要通过数据结构画图来说明白:
String
字符串结构如下:
一旦Matcher对象建好,那么就会自动分配头尾两个指针。调用一次find方法,就会进行一次匹配操作。 第一次调用后,匹配到了abc三个字符,此时指针指向为:
此时调用start方法, 返回的就是上一次匹配操作之后,start指针指向的位置,为第一个字符的左边,调用end方法,返回的是end指针的位置,为第三个字符右边。所以,第一次调用start方法,返回结果为0,调用end方法返回结果为3。
第二次调用find方法后,指针向前移动:
此时调用start方法,返回3,调用end方法返回6。
以此类推,直到find方法返回false,匹配结束。
经过上面的数据结构分析可知,调用一次find方法得到的匹配内容,就称为“上一次匹配”,很多方法都必须依赖于find方法:比如说,start、end、group、groupCount, 还有reset方法虽然不直接依赖于find方法,但是也息息相关,调用reset方法后,头尾指针都将归零,重新开始。
正则分组
介绍完Matcher类的数据结构以后,继续介绍正则表达式中的另一个重要概念,正则分组。 正则分组主要是用于提取出,指定字符串中特定的子字符串。
正则分组,有两个重要的点:
1. ( ) 小括号的里面的内容分为一组,一个正则有n个小括号,就表示要分成n+1组,其中第0组,是全部匹配内容。
2. find, group,以及groupCount等相关方法。
正则分组分为捕获组、分组取名、非捕获组、分组复用,下面的例子将分别进行说明。
举例说明1 捕获组:
// 目标字符串,目标是要提前IOPS,avg的值
1. 对于正则表达式, ^ 匹配字符串开始位置; .* 匹配几个空格;IOPS=匹配IOPS=;d+匹配2932,作为第1组内容;b匹配2与,之间的位置;.* 匹配, bw=329,and other number ;b匹配空格与a之间的位置; avg=匹配avg=; d+匹配399;b匹配9与逗号之间的位置; .*匹配, savg=23029; $匹配结束位置。
2. 调用一次find方法,将匹配到全部字符串内容; 整个匹配内容被分成了三组,第0组是全部字符串内容,第1组得到2932, 第2组内容是399; 调用groupCount,不包括第0组,所以结果为2。
举例说明2 分组命名:
在进行分组设置的时候,还可以取组名。 取名格式为: (?<name>exp), 然后用matcher.group(“groupName”) 取出组内匹配的内容
String
举例说明3 非捕获组:
在进行分组的时候,可以给某些不那么重要的组,只分组不编号也不取名字。非捕获组的格式为: (?:exp)
// 目标字符串,获取avg的值
可以看到,(?:d+) 匹配内容,但是不捕获文本,也不进行分组编号。整个字符串,除了第0组外,只有第1组。
举例说明4 分组复用:
正则分组后的复用。这个使用,主要牵扯到replaceFirst或者replaceAll方法。
// 目标字符串为手机号
该程序将把手机号进行模糊处理, 整个正则分为3组,第1组为前3位数字,第2组为后4位数字,所以替换时,使用$n,来表示引用第n组的内容。所以本例的输出结果为: 183****6765