正则表达式三种匹配模式:贪婪模式,勉强模式,占有模式的区别
我在做项目的时候,曾领教过正则“回溯陷阱”的厉害,所以,今天做个总结下正则常见的两种模式的区别:
【贪婪模式】:正则表达式一般趋向于最大长度匹配,总是尝试匹配尽可能多的字符,也就是所谓的贪婪匹配;
【勉强模式】:又叫"勉强模式",属于最小长度匹配,就是匹配到结果就好,总是尝试匹配尽可能少的字符;
【占有模式】:又叫"勉强模式",属于最小长度匹配,就是匹配到结果就好,总是尝试匹配尽可能少的字符;
如何区分:
Java 正则表达式默认是贪婪模式(.*),在量词后面直接加上一个问号?就是勉强模式(.*?),也就是非贪婪模式;而在量词后面直接加上一个加号 + 就是非贪婪模式(.*+)。
原理分析:
假设待处理的字符串是 :xfooxxxxxxfoo
1. 贪婪模式
模式分为子模式p1(.*)和子模式p2(foo)两个部分. 其中p1中的量词匹配方式使用默认方式(贪婪型)。
匹配开始时,吃入所有字符xfooxxxxxx去匹配子模式p1。匹配成功,但这样以来就没有了字符串去匹配子模式p2。本轮匹配失败;第二轮:减少p1部分的匹配量,吐出最后一个字符, 把字符串分割成xfooxxxxxxfo和o两个子字符串s1和s2。 s1匹配p1, 但s2不匹配p2。本轮匹配失败;第三轮,再次减少p1部分匹配量,吐出两个字符, 字符串被分割成xfooxxxxxxfo和oo两部分。结果同上。第四轮,再次减少p1匹配量, 字符串分割成xfooxxxxxx和foo两个部分, 这次s1/s2分别和p1/p2匹配。停止尝试,返回匹配成功。
2. 勉强模式(非贪婪模式)
第一次尝试匹配, p1由于是0或任意次,因此被忽略,用字符串去匹配p2,失败;第二次,读入第一个字符x, 尝试和p1匹配, 匹配成功; 字符串剩余部分fooxxxxxxfoo中前三个字符和p2也是匹配的. 因此, 停止尝试, 返回匹配成功。在这种模式下,如果对剩余字符串继续去寻找和模式相匹配的子字符串,还会找到字符串末尾的另一个xfoo,而在贪婪模式下,由于第一次匹配成功的子串就已经是所有字符,因此不存在第二个匹配子串。
3. 占有模式
匹配开始时读入所有字符串, 和p1匹配成功, 但没有剩余字符串去和p2匹配。因此, 匹配失败。返回。
案例:
[code]String test1 = "a<tr>aava</tr>abb "; String test2 = "<tr>"; String reg1 = "<.+>"; System.out.println("贪婪匹配结果:" + test1.replaceAll(reg1,"###")); String reg2 = "<.+?>"; System.out.println("勉强匹配结果:" + test1.replaceAll(reg2,"###")); String reg3 = "<.++>"; String reg4 = "<tr>"; System.out.println("占有匹配结果1:" + test1.replaceAll(reg3, "###")); System.out.println("占有匹配结果2:" + test2.replaceAll(reg4, "###")); 输出结果为: 贪婪匹配结果:a###abb 勉强匹配结果:a###aava###abb 占有匹配结果1:a<tr>aava</tr>abb 占有匹配结果2:###
总结:
- 贪婪匹配模式属于最大长度匹配,正则表达式引擎会一直匹配到字符串最后,当匹配为false时,通过回溯的方式,倒退找到倒数第一个匹配位置,返回匹配结果;也就是说,这种匹配方式会尽量大范围的匹配,直到匹配了整个内容,这时发现匹配不能成功时,开始回退缩小匹配范围,直到匹配成功
- 勉强匹配模式于最小长度匹配,正则表达式引擎会匹配到符合pattern的末尾位置那个字符,然后再往后走一步,发现匹配为false,又回溯到找到回退的最近一个匹配为true的位置,返回结果。只要匹配成功,就不再继续尝试匹配更大范围的内容。
- 占有匹配与贪婪匹配有一定的相似性,那就是都尽量匹配最大范围的内容,直到内容结束,但与贪婪匹配不同的是,完全匹配不再回退尝试匹配更小的范围。
更多精彩,请关注我的"今日头条号":Java云笔记
随时随地,让你拥有最新,最便捷的掌上云服务
- JAVA 正则表达式的三种模式: 贪婪, 勉强和占有的讨论
- Java-----正则表达式匹配模式[贪婪模式、勉强模式、占有模式]
- 正则表达式的三种模式【贪婪、勉强、侵占】的分析
- 正则表达式的三种模式【贪婪、勉强、侵占】的分析
- 正则表达式笔记 3 贪婪、勉强、独占三种匹配量词
- Java 正则表达式 量词 --- 三种匹配模式【贪婪型、勉强型、占有型】
- Java正则表达式 贪婪 勉强 匹配说明 greedy vs ( lazy | reluctant )
- 浅谈php正则表达式中的非贪婪模式匹配的使用
- [疯狂Java]正则表达式:Java正则表达式语法、贪婪模式/勉强模式
- 【转载】JAVA正则表达式的三种模式的区别-greedy reluctant possessive
- php正则表达式中的非贪婪模式匹配
- python 正则表达式 贪婪模式的简介和匹配时的几种模式
- Java 正则表达式 量词 --- 三种匹配模式【贪婪型、勉强型、占有型】
- 正则表达式:表达式的递归匹配及非贪婪模式的效率
- Java 正则表达式 量词 --- 三种匹配模式【贪婪型、勉强型、占有型】
- php正则表达式中的非贪婪模式匹配的使用
- Python 正则表达式里面 贪婪模式和非贪婪模式的区别
- 正则表达式贪婪模式及最短匹配
- 浅谈php正则表达式中的非贪婪模式匹配的使用
- 正则表达式中贪婪和非贪婪(惰性)匹配的区别与效率问题