正则表达式的使用无非就四个步骤:
- 定义匹配规则,就是一串负责正则表达式语法的字符串,我们叫它patternStr
- 使用Pattern类去编译patternStr,得到Pattern实例patternIns(注意Pattern并没有提供公共构造方法)
- 使用patternIns的matcher方法解析需要匹配的字符串targetStr,得到Matcher类的实例matcherIns
有了matcherIns,你就可以:
1) 查找是否有匹配规则的字符 matcherIns.find()
2) 获取匹配后的分组matcherIns.group()
……..
正则表达式在实际的项目中用得很少,过一段时间后就很容易忘记,偶尔翻看了下以前正则表达式的资料,发现了个有趣的例子。
这是一段测试捕获组的代码,引用自runoob.com:
http://www.runoob.com/java/java-regular-expressions.html
捕获组
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
例如,正则表达式 (dog) 创建了单一分组,组里包含”d”,”o”,和”g”。
捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组:
((A)(B(C)))
(A)
(B(C))
(C)
可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。
还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。
先上代码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PatternDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
String line = "This order was placed for QT3000a! OK?";
String patternStr = "(.*)(\\d+)(.*)";
Pattern p = Pattern.compile(patternStr);
Matcher m = p.matcher(line);
System.out.println("Match num = " + m.groupCount());
if(m.find()){
System.out.println(m.group(0));
System.out.println(m.group(1));
System.out.println(m.group(2));
}else{
System.out.println("NO MATCH");
}
}
}
运行后我们得到如下结果:
Match num = 3
This order was placed for QT3000a! OK?
This order was placed for QT300
0
这个时候我懵逼了,第二个匹配规则(\d+)不是指匹配*到多个数字吗,为什么没有匹配整个数字串3000,仅仅匹配了0 ?
而(.*)却也只是匹配了This order was placed for QT300, 不是 This order was placed for QT3000a! OK?
这成功引起了我的注意
华丽的分割线
我们看到,Match num = 3,也就是说,我们还有一个捕获组还没打印出来,来,我们加上
System.out.println(m.group(3));
运行结果:
Match num = 3
This order was placed for QT3000a! OK?
This order was placed for QT300
0
a! OK?
嗯…剩下的匹配看起来木有问题…. 那么问题出在哪里呢? 让我们多做几个实验,首先我们修改匹配规则串patternStr,多加一个数字匹配(\d+):
String patternStr = "(.*)(\\d+)(\\d+)(.*)";
得到的结果是这样的:
Match num = 4
This order was placed for QT3000a! OK?
This order was placed for QT30
0
0
a! OK?
噢?! group(1)少匹配了一个0,很明显这个0被新加的(\d+)夺走了,我再改一下,把(\d+)改成(\d*)
String patternStr = "(.*)(\\d+)(\\d*)(.*)";
结果
Match num = 4
This order was placed for QT3000a! OK?
This order was placed for QT300
0
a! OK?
group(3)的0被夺走了… 最后一个实验
String patternStr = "(.*)(\\d*)(\\d*)(.*)";
结果,为了让大家知道各个分组的位置,我用<–group(num)标记了一下
Match num = 4
This order was placed for QT3000a! OK? <--group(0)
This order was placed for QT3000a! OK?<--group(1)
<--group(2)
<--group(3)
<--group(4)
终于有头绪了,捕获组的匹配都是贪婪模式的,越是排在前面的捕获组,匹配的优先级就越高,在满足其余捕获组的最低要求(如 + 最低要求匹配一个)的前提下,优先级越高的捕获组,会尽可能地匹配所有符合的字符。
至此,一切真相大白,温故而知新,这句话一点都没错!!
脑袋空空,口袋空空!