java正则表达式 中 Greedy 、Reluctant 、Possessive数量词的区别

Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
 
Reluctant 数量词
X?? X,一次或一次也没有
X*? X,零次或多次
X+? X,一次或多次
X{n}? X,恰好 n 次
X{n,}? X,至少 n 次
X{n,m}? X,至少 n 次,但是不超过 m 次
 
Possessive 数量词
X?+ X,一次或一次也没有
X*+ X,零次或多次
X++ X,一次或多次
X{n}+ X,恰好 n 次
X{n,}+ X,至少 n 次
X{n,m}+ X,至少 n 次,但是不超过 m 次

 Greedy 、Reluctant 、Possessive数量词的区别

1、Greedy(贪婪的)数量词

Greedy被认为是"贪婪的",因为它们在尝试第一次匹配之前强制匹配器读入或吃掉整个输入字符串。它的特性是一次性地读入整个字符串,如果不匹配就吐掉最右边的一个字符再匹配,直到找到匹配的字符串或字符串的长度为0为止。它的宗旨是读尽可能多的字符,所以当读到第一个匹配时就立刻返回。

例如

public static void testGreedy() {
		Pattern p = Pattern.compile(".*foo");
		String strText = "xfooxxxxfoo";
		Matcher m = p.matcher(strText);
		while (m.find()) {
			System.out.println("matched form " + m.start() + " to " + m.end());
		}
		System.out.println(m.matches());
	}

输出

matched form 0 to 11
true

此例中,正则“.*foo”中的“.*”首先消耗了整个字符串,所以匹配肯定不成功。然后匹配器一次后退一个字符,一直后退到最右侧出现“foo”为止,这里匹配成功并且搜索停止。或者这样理解,为了整个表达式能匹配成功,“.*”虽然可以读入整个表达式,但它还是“主动让出”foo这3个它本可读入的字符空间。

2、Reluctant(不情愿的)数量词

Reluctant被认为是"不情愿的",因为它们从输入字符串的开头开始,然后不情愿地一次吃一个字符寻找匹配。它的特性是从字符串的左边开始,试图不读入字符串中的字符进行匹配,失败,则多读一个字符,再匹配,如此循环,当找到一个匹配时会返回该匹配的字符串,然后再次进行匹配直到字符串结束。

例如

public static void testReluctant() {
		Pattern p = Pattern.compile(".*?foo");
		String strText = "xfooxxxxfoo";
		Matcher m = p.matcher(strText);
		while (m.find()) {
			System.out.println("matched form " + m.start() + " to " + m.end());
		}
		System.out.println(m.matches());
	}

输出

matched form 0 to 4
matched form 4 to 11
true

此例中,正则“.*?foo”中的“.*?”,它试图0消耗的匹配字符串,但失败,不得不再读入(消耗)一个字符再进行匹配,这时xfoo符合要求,返回之(xfoo),再读入,直到末尾时找到xxxxfoo匹配又返回之,这时已经没有东西可读了,结束匹配。

3、Possessive(占有的)数量词

Possessive被认为是"永不退缩的",因为占有量词总是占用整个输入字符串,尝试一次(并且只有一次)匹配。与贪婪的量词不同,占有量词永远不会退缩,即使这样做也会使整体匹配成功。他的特性,就是与贪婪模式相比,他不会往外吐出。

例子

	public static void testPossessive() {
		Pattern p = Pattern.compile(".*+foo");
		String strText = "xfooxxxxfoo";
		Matcher m = p.matcher(strText);
		while (m.find()) {
			System.out.println("matched form " + m.start() + " to " + m.end());
		}
		System.out.println(m.matches());
	}

输出

false

此例中,正则“.*+foo”中的“.*+”首先消耗了整个字符串,所以匹配不成功,由于它不回吐,所以匹配结束。

使用占有量词来表示你想要抓住所有东西而不会退缩的情况; 在没有立即找到匹配的情况下,它将胜过等效的贪婪量词。

参考资料:https://docs.oracle.com/javase/tutorial/essential/regex/quant.html
 

猜你喜欢

转载自blog.csdn.net/qq_36418435/article/details/81357785