Java:正则匹配的不同情况(贪婪,勉强): greedy, reluctant, possesive
2013-02-04 14:16
351 查看
转自:http://www.cppblog.com/biao/archive/2010/02/05/107298.html
贪婪、勉强和侵占量词间的不同
在贪婪、勉强和侵占三个量词间有着细微的不同。
贪婪(*, ?, +):读入整个串,从后往前匹配
勉强(*?, ??, +?):从前往后匹配
侵占(*+, ?+, ++):读入整个串,从前往后匹配,匹配的是整个串
贪婪量词之所以称之为“贪婪的”,这是由于它们强迫匹配器读入(或者称之为吃掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了。赖于在表达式中使用的量词,最终它将尝试地靠着 1 或 0 个字符的匹配。
但是,勉强量词采用相反的途径:从输入字符串的开始处开始,因此每次勉强地吞噬一个字符来寻找匹配,最终它们会尝试整个输入的字符串。
最后,侵占量词始终是吞掉整个输入的字符串,尝试着一次(仅有一次)匹配。不像贪婪量词那样,侵占量词绝不会回退,即使这样做是允许全部的匹配成功。
为了说明一下,看看输入的字符串是 xfooxxxxxxfoo 时。
第一个例子使用贪婪量词
然而,第二个例子采用勉强量词,因此通过首次消耗“什么也没有”作为开始。由于“foo”并没有出现在字符串的开始,它被强迫吞掉第一个字母(“x”),在 0 和 4 处触发了第一个匹配。测试用具会继续处理,直到输入的字符串耗尽为止。在 4 和 13 找到了另外一个匹配。
第三个例子的量词是侵占,所以在寻找匹配时失败了。在这种情况下,整个输入的字符串被
你可以在想抓取所有的东西,且决不回退的情况下使用侵占量词,在这种匹配不是立即被发现的情况下,它将会优于等价的贪婪量词。
import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { public static void main(String[] args) { String str = "<biao><>c<b>"; Pattern pattern; Matcher matcher; // 贪婪: 最长匹配 .* : 输出: <biao><>c<b> pattern = Pattern.compile("<.*>"); matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group()); } // 不知是否非贪婪 .*? : 输出: <biao>, <>, <b> pattern = Pattern.compile("<.*?>"); matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group()); } // 使用组, 输出<>里的内容, 输出: 'biao', ' ', 'b' // 0组代表整个表达式, 子组从1开始 pattern = Pattern.compile("<(.*?)>"); matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group(1)); } } }
贪婪、勉强和侵占量词间的不同
在贪婪、勉强和侵占三个量词间有着细微的不同。
贪婪(*, ?, +):读入整个串,从后往前匹配
勉强(*?, ??, +?):从前往后匹配
侵占(*+, ?+, ++):读入整个串,从前往后匹配,匹配的是整个串
贪婪量词之所以称之为“贪婪的”,这是由于它们强迫匹配器读入(或者称之为吃掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了。赖于在表达式中使用的量词,最终它将尝试地靠着 1 或 0 个字符的匹配。
但是,勉强量词采用相反的途径:从输入字符串的开始处开始,因此每次勉强地吞噬一个字符来寻找匹配,最终它们会尝试整个输入的字符串。
最后,侵占量词始终是吞掉整个输入的字符串,尝试着一次(仅有一次)匹配。不像贪婪量词那样,侵占量词绝不会回退,即使这样做是允许全部的匹配成功。
为了说明一下,看看输入的字符串是 xfooxxxxxxfoo 时。
Enter your regex: .*foo // 贪婪量词 Enter input string to search: xfooxxxxxxfoo I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13. Enter your regex: .*?foo // 勉强量词 Enter input string to search: xfooxxxxxxfoo I found the text "xfoo" starting at index 0 and ending at index 4. I found the text "xxxxxxfoo" starting at index 4 and ending at index 13. Enter your regex: .*+foo // 侵占量词 Enter input string to search: xfooxxxxxxfoo No match found.
第一个例子使用贪婪量词
.*,寻找紧跟着字母“f”“o”“o”的“任何东西”零次或者多次。由于量词是贪婪的,表达式的
.*部分第一次“吃掉”整个输入的字符串。在这一点,全部表达式不能成功地进行匹配,这是由于最后三个字母(“f”“o”“o”)已经被消耗掉了。那么匹配器会慢慢地每次回退一个字母,直到返还的“foo”在最右边出现,这时匹配成功并且搜索终止。
然而,第二个例子采用勉强量词,因此通过首次消耗“什么也没有”作为开始。由于“foo”并没有出现在字符串的开始,它被强迫吞掉第一个字母(“x”),在 0 和 4 处触发了第一个匹配。测试用具会继续处理,直到输入的字符串耗尽为止。在 4 和 13 找到了另外一个匹配。
第三个例子的量词是侵占,所以在寻找匹配时失败了。在这种情况下,整个输入的字符串被
.*+消耗了,什么都没有剩下来满足表达式末尾的“foo”。
你可以在想抓取所有的东西,且决不回退的情况下使用侵占量词,在这种匹配不是立即被发现的情况下,它将会优于等价的贪婪量词。
相关文章推荐
- Java-----正则表达式匹配模式[贪婪模式、勉强模式、占有模式]
- java: 正则匹配字符串中多个目标子串(贪婪匹配的模拟实现)
- java正则表达式的匹配结果遍历方法find()和matches()不同
- java 正则贪婪匹配
- 总算是明白 java正则表达式 中 Greedy 、Reluctant 、Possessive数量词的区别了
- java正则表达式——Greedy、Reluctant和Possessive
- 勉强和贪婪的正则匹配的工作方式
- java中正则匹配的贪婪模式和非贪婪模式
- java基础巩固系列(十三):java正则表达式中的数量词:Greedy、Reluctant、Possessive
- Java 与PHP 在正则表达式匹配上的一点小不同
- [疯狂Java]正则表达式:Java正则表达式语法、贪婪模式/勉强模式
- java 正则匹配 特殊字符 减号- 的情况,处理方式
- java 正则(4) 不常用 / 贪婪匹配 / 非捕获组 / 向前引用 / flag 简写
- Java正则之贪婪匹配,惰性匹配
- Java正则表达式学习 贪婪 勉强 侵占
- Java正则表达式学习 贪婪 勉强 侵占
- Java正则中的Greedy、Reluctant 、Possessive qualifier
- Java正则之贪婪匹配、惰性匹配
- Java正则中的Greedy、Reluctant 、Possessive
- Java正则表达中Greedy Reluctant Possessive 的区别