前言:最开始看的是这篇文章“Java正则表达中Greedy Reluctant Possessive 的区别”来进行学习理解,但是发现这篇文章说得并不是很清楚,经过最终领悟,现在将自己的理解作为笔记分享出来。
从Java的官方文档中我们可以看到,正则表达式表示数量词的符号有三套,分别是Greedy(贪婪的)、Reluctant(勉强的)和Possessive(独占的)。
通过官方文档对比我们可以看出规律:
贪婪模式即在X字符后面增加限定符号如:?、*、+、{n}、{n,}、{n,m}
懒惰模式是在带有限定符号:?、*、+、{n}、{n,}、{n,m}的后面,增加”?”,如:X??
独占模式也叫侵占模式,是在带有限定符号:?、*、+、{n}、{n,}、{n,m}的后面,增加”+”,如:X?+
用代码说话
1、Greedy 贪婪模式
public static void main(String[] args) {
String targetStr = "xfooxxxxxxxfoo";
Pattern pattern = Pattern.compile(".*foo");
Matcher matcher = pattern.matcher(targetStr);
while (matcher.find()) {
System.out.println("find text = "
+ matcher.group()
+ " start index = "
+ matcher.start()
+ " end index = "
+ matcher.end());
}
}
输出结果:
find text = xfooxxxxxxxfoo start index = 0 end index = 14
2、Reluctant 懒惰模式
public static void main(String[] args) {
String targetStr = "xfooxxxxxxxfoo";
Pattern pattern = Pattern.compile(".*?foo");
Matcher matcher = pattern.matcher(targetStr);
while (matcher.find()) {
System.out.println("find text = "
+ matcher.group()
+ " start index = "
+ matcher.start()
+ " end index = "
+ matcher.end());
}
}
输出结果:
find text = xfoo start index = 0 end index = 4
find text = xxxxxxxfoo start index = 4 end index = 14
3、Possessive 独占模式
public static void main(String[] args) {
String targetStr = "xfooxxxxxxxfoo";
Pattern pattern = Pattern.compile(".*+foo");
Matcher matcher = pattern.matcher(targetStr);
while (matcher.find()) {
System.out.println("find text = "
+ matcher.group()
+ " start index = "
+ matcher.start()
+ " end index = "
+ matcher.end());
}
}
输出结果为空白,即matcher.find()返回false,未匹配成功.
下面说说原理:
Greedy“贪婪模式”是因为匹配器被强制要求第一次尝试匹配时就读入整个输入串,如果第一次尝试匹配失败,则从后往前逐个字符地回退并尝试再次匹配,直到匹配成功或没有字符可回退。
模式串:.*foo
查找串:xfooxxxxxxxfoo
结果:find text = xfooxxxxxxxfoo start index = 0 end index = 14
要点:一次性读入整个输入串,第一次匹配整个字符串时,符合 .* ,此时到达末尾,回退1个字符,继续进行第二次匹配,依次类推,直到回退到 foo时,匹配成功,此时 match.find()==true,输出结果
Reluctant采用与Greedy相反的方法,它从输入串的首字符位置开始,在一次尝试匹配查找中只勉强地读一个字符,直到尝试完整个字符串。
模式串:.*?foo
查找串:xfooxxxxxxxfoo
结果: find text = xfoo start index = 0 end index = 4
find text = xxxxxxxfoo start index = 4 end index = 14
这个应该也很容易理解,主要思想同greedy,只是首次读入是从头开始。
最难理解的应该是独占模式吧(其实特别简单,哈哈):
Possessive(独占模式)同greedy一样一次性读入整个输入串,但是只尝试一次仅且一次,Possessive从不回退.
(参考greedy的图的第一次匹配,区别在于执行第一次匹配后不再进行第二次回退匹配,直接返回matcher.find结果)
根据greedy要点推出,当第一次读取匹配时,读取在末尾,此时只符合. ,并未匹配到foo,所以直接返回matcher.find()== false
模式串:.+foo
查找串:xfooxxxxxxxfoo
结果:
//未匹配成功
到此,应该就明白了吧!
简单总结一下:
贪婪性:能够使匹配成功的最大可能重复数
勉强性:匹配最小的重复次数
独占性:即使让整个匹配失败,也要匹配最大的重复数。
下面来个”独占模式”成功匹配的例子
目标匹配字段:adbcde
匹配模式:[a-z]*+
匹配结果,匹配成功,mactcher.find()==true,matcher.group()==””,匹配成功的开始位置为6,结束位置为6,刚好是目标匹配字符的长度
public static void main(String[] args) {
String targetStr = "adbcde";
Pattern pattern = Pattern.compile("[a-z]*+");
Matcher matcher = pattern.matcher(targetStr);
while (matcher.find()) {
System.out.println(matcher.find());
System.out.println("find text = "
+ matcher.group()
+ " start index = "
+ matcher.start()
+ " end index = "
+ matcher.end());
}
}
结果输出:
true
find text = start index = 6 end index = 6
个人觉得独占模式的使用率不高,因为太严格了,严格到没出路!!!