正则数量词及非捕获

一、数量词: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());

上面例子都理解了,非捕获基本也就理解了,不过实际中用的也不多

时间: 2024-09-28 11:36:30

正则数量词及非捕获的相关文章

Python中正则匹配使用findall,捕获分组(xxx)和非捕获分组(?:xxx)的差异

转自:https://blog.csdn.net/qq_42739440/article/details/81117919 下面是我在用findall匹配字符串时遇到的一个坑,分享出来供大家跳坑. 例题: 如图所示: 正则a和正则b两个式子匹配出来的结果是不同的. 那 ?: 的作用就是把捕获分组转变为非捕获分组. 什么是捕获组和非捕获组呢? (qq|163|126) ---> 这样单独的括号就为捕获组 (?:qq|163|126) ---> 这样在原有分组里加上?: 就把捕获组转变为一个非捕获

正则表达式中的捕获和非捕获

之前我们在做例子的时候,我们看到过这种捕获的形式,我们也试过反向引用.那像我们捕获的内容,可以通过一个正则表达式的模式,或者部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储.缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式.每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数.当然,如果我们不想捕获我们的文本,可以使用非捕获元字符 '?:'.'?=' 或 '?!' 来重写捕获

正则表达式 1. 分组提取/非捕获组

https://www.zybuluo.com/Zjmainstay/note/709093 1. 分组提取/非捕获组 分组,是正则里一个非常重要的概念,我们需要针对某个区域提取数据,往往需要依赖分组.而分组,其实就是正则里()括住的部分. (1.1)分组提取 需求:在分组1中匹配meta中author属性的值源串:<meta author="Zjmainstay" />another author="Zjmainstay too"预期:分组1得到Zjm

JavaScript正则表达式-非捕获性分组

非捕获性分组定义子表达式可以作为整体被修饰但是子表达式匹配结果不会被存储. 非捕获性分组通过将子表达式放在"?:"符号后. str = "img1.jpg,img2.jpg,img3.bmp"; reg = /(?:\w*)(?=\.gif)/; arr_m = str.match(reg);//arr_m = ["img1","img2"]

正则表达式 非捕获性分组

非捕获性分组语法为(?:pattern),即将pattern部分组合成一个可统一操作的组合项,但不把这部分内容当作子匹配捕获,匹配的内容部进行编号也不存储在缓冲区中供以后使用.非捕获性分组方法在必须进行组合.但又不想对组合的部分进行缓存的情况下非常有用. 例如,要在一篇英文资料中查找"program"和"project"两个单词,正则表达式可表示为/program|project/,也可表示为/pro(gram|ject)/,但是缓存子匹配(gramject)没有意

Capturing versus non-capturing lambdas 捕获和非捕获的Lambda表达式

Capturing versus non-capturing lambdas Lambdas are said to be "capturing" if they access a non-static variable or object that was defined outside of the lambda body. For example, this lambda captures the variablex: int x = 5; return y -> x +

php 正则表达式捕获组与非捕获组

熟练掌握正则表达式是每个程序员的基础要求,对于每个初学者来说会被正则表达式一连串字符弄得头晕眼花.博主便会如此,一直对正则表达式有种莫名的恐惧.近来看到另一位博友写的 <php正则表达式>一文获益良多,对其通配符以及捕获数据两个章节颇感兴趣.这两个章节正好涉及到的是正则表达式的捕获组与非捕获组的知识,因而本文来细细探讨下这部分知识. 我们知道,在正则表达式下(x) 表示匹配'x'并记录匹配的值.这只是比较通俗的说法,甚至说这是不严谨的说法,只有()捕获组形式才会记录匹配的值.非捕获组则只匹配,

正则表达式分组捕获非捕获的示例理解

举几个例子 一.使用捕获型() 比如0.23 1.(^\d+)(\.)(\d{0,2}) 正则表达式有3个()使用match就会产生3个分组 2.^\d+\.\d{0,2} 没有(),不产生分组 二.非捕获型(?:) (?:^\d+)(\.)(\d{0,2}) 第一个分组不再捕获 原文地址:https://www.cnblogs.com/zhaogaojian/p/12207959.html

JS 正则中的命名捕获分组

假设你在一段陌生的代码中看到这样一个函数: function toLocalDate(date) { return date.replace(/(\d{2})-(\d{2})-(\d{4})/, "$2-$1-$3") } 单看这个函数你能知道它是想把“日-月-年”替换成“月-日-年”,还是反过来?匿名捕获分组没法做到这一点,那就该命名捕获分组上场了: function toLocalDate(date){ return date.replace(/(?<month>\d{