一、数量词:Greedy Reluctant Possessive
String str = "abcdabg"; // ①Greedy // output:abcdab Pattern pattern1 = Pattern.compile(".*ab"); Matcher matcher1 = pattern1.matcher(str); while (matcher1.find()) { System.out.print(matcher1.group() + " "); } System.out.println(); // ②Reluctant // output:ab cdab Pattern pattern2 = Pattern.compile(".*?ab"); Matcher matcher2 = pattern2.matcher(str); while (matcher2.find()) { System.out.print(matcher2.group() + " "); } System.out.println(); // ③Possessive // no output Pattern pattern3 = Pattern.compile(".*+ab"); Matcher matcher3 = pattern3.matcher(str); while (matcher3.find()) { System.out.println(matcher3.group()); }1.Greedy:贪婪,表示匹配的时候先匹配整个字符串,如果匹配成功,则终止,如果不匹配,再从右向左一个一个吐出来(因为他太贪婪了),过程如下:
模式:.*ab,要匹配的字符abcdabg,注意是.*来匹配
1.先匹配abcdabg,不成功
2.匹配abcdab,还是不成功
3.匹配abcda,还是不成功
4.匹配abcd,匹配成功,后面刚好是ab
所以最终输出的是abcdab
2.Reluctant 勉强,匹配过程是从左到右,先从最左边吃掉一个字符,不匹配的话接着吃点(我很不愿意,所以很勉强),一直到匹配的,但这时不会退出,而是继续匹配,过程如下:
模式:.*?ab,要匹配的字符abcdabg,注意是.*来匹配
1.先匹配a,不成功
2.匹配ab,成功,继续匹配
3.匹配c,不成功
4.匹配cd,成功,后面刚好是ab
5.匹配cda,不成功,继续匹配到末尾
所以最终输出的是ab cdab
3.Possessive 侵占,表示我一次性匹配整个字符串,而且只匹配一次,要么成功,要么不成功 模式:.*+ab,要匹配的字符abcdabg,注意是.*来匹配
1.直接匹配abcdabg,.*直接吃掉整个字符串了,没有字符来匹配后面的ab了,当然是不匹配了,然后就终止了,所以没有任何输出
二、捕获与非捕获
这2个都是用()来包起来的,看下面的例子就知道2者的区别了
String str = "industries"; // ①捕获 Pattern pattern1 = Pattern.compile("industr(y|ies)"); Matcher matcher1 = pattern1.matcher(str); while (matcher1.find()) { System.out.println(matcher1.group(0) + "+++" + matcher1.group(1)); } // ②非捕获 Pattern pattern2 = Pattern.compile("industr(?:y|ies)"); Matcher matcher2 = pattern2.matcher(str); while (matcher2.find()) { System.out.println(matcher1.group(0) + "+++" + matcher2.group(1)); }结果为:
industries+++ies Exception in thread "main" java.lang.IllegalStateException: No match found at java.util.regex.Matcher.group(Matcher.java:468) at com.reg.TestAt.main(TestAt.java:47)
对于捕获的,()会被当做一个分组,所以还有一个小标为1的组
但是对于非捕获,是没有组的,所以就出现下标异常了
三、非捕获
直接看下面的例子比较容易理解:
System.out.println("---------(?=X)---------"); // lookahead 向后看 // (?=X) X,通过零宽度的正 lookahead /*表达式"a(?=b)c"不能匹配"abc",也不能匹配"ac"、"ab"。而且不能匹配任何字符串。因为其预测匹配a的位置后,应该是b,但是,又要求a之后是c。 表达式"a(?=b)bc"是可以匹配"abc"的,但是不能匹配"ab"和"ac"。*/ Pattern p1 = Pattern.compile("a(?=c)"); System.out.println(p1.matcher("ac").matches());// 这种是不包含的,所以为false,对比下面的 Matcher matcher1 = p1.matcher("ac"); while(matcher1.find()) { System.out.println(matcher1.group());// 结果为a } System.out.println("---------(?>X)---------"); Pattern p11 = Pattern.compile("a(?>c)"); System.out.println(p11.matcher("ac").matches());// 这种是包含的,所以为true,对比上面的 Matcher matcher11 = p11.matcher("ac"); while(matcher11.find()) { System.out.println(matcher11.group()); } System.out.println("---------(?!X)---------"); // (?!X) X,通过零宽度的负 lookahead // a(?!c)b 表示a后面不能是c,且是b,所以为true Pattern p2 = Pattern.compile("a(?!c)b");// a(?!b)b System.out.println(p2.matcher("ab").matches()); System.out.println("---------(?<=X)---------"); // lookbehind 向前看 // (?<=X) X,通过零宽度的正 lookbehind // a(?<=a)c 表示c前面必须是a Pattern p3 = Pattern.compile("a(?<=a)c"); System.out.println(p3.matcher("ac").matches()); System.out.println("---------(?<!X)---------"); // (?<!X) X,通过零宽度的负 lookbehind // b(?<!a)c 表示c前面不能是a,且必须是b Pattern p4 = Pattern.compile("(?<!a)c"); System.out.println(p4.matcher("c").matches()); Matcher matcher4 = p4.matcher("ecb"); while(matcher4.find()) { System.out.println(matcher4.group()); } System.out.println("---------(?idmsux-idmsux)---------"); // 一共有:i d m s u x 这些个值,其实对应一些常量,见下面 Pattern p12 = Pattern.compile("(?i)abc");// i表示CASE_INSENSITIVE,不区分大小写;(?-i)表示否定,即区分大小写 System.out.println(p12.matcher("aBc").matches()); Matcher matcher12 = p12.matcher("aBc"); while(matcher12.find()) { System.out.println(matcher12.group()); } // 这种方式和上面的效果一样,看你喜欢哪一种 Pattern p13 = Pattern.compile("abc", Pattern.CASE_INSENSITIVE); System.out.println(p13.matcher("aBc").matches()); Matcher matcher13 = p13.matcher("aBc"); while(matcher13.find()) { System.out.println(matcher13.group()); } System.out.println("---------(?idmsux-idmsux:X)---------"); Pattern p14 = Pattern.compile("(?i:efg)ab"); System.out.println(p14.matcher("eFGabc").matches()); Matcher matcher14 = p14.matcher("eFGabc"); while(matcher14.find()) { System.out.println(matcher14.group()); } System.out.println("--------- Appendix ---------"); // (?:X) X,作为非捕获组 // (?>X) X,作为独立的非捕获组 // 指针会移动(是包含在内的),注意和(?=X)的区别 Pattern p5 = Pattern.compile("a(?:b)"); System.out.println(p5.matcher("ab").matches()); Pattern p9 = Pattern.compile("a(?>b)"); System.out.println(p9.matcher("ab").matches());上面例子都理解了,非捕获基本也就理解了,不过实际中用的也不多