Java 正则表达式中量词的贪婪型,勉强型和占有型讲解

来源:互联网 发布:数据库 锁定客户群 编辑:程序博客网 时间:2024/04/29 15:20
今天在做markdown转换器项目时遇到了一个问题,让我回顾了一下正则表达式中量词的贪婪型,勉强型和占有型这三种类型的匹配方式。这些匹配方式在匹配时需要根据项目需求合理地选择搭配,否则程序结果可能完全出乎你的意料。

我的问题是,有如下字符串:“This is [google][1],this is [apple][2],and this is [ms][3].”
我需要依次将“[google][1]”,“[apple][2]”,“[ms][3]”给扫描出来。

最初我的做法是写了如下的表达式:
Pattern pattern="\\[.+\\]\\[.+\\]"; 
我通过matcher.find()判断是否找到,通过matcher.group()获取扫描到的子串,可是当我运行程序后,却只得到了[google][1],this is [apple][2],and this is [ms][3],由此引出了三种匹配类型这一问题。

java正则表达式默认匹配是贪婪型(最大匹配),也就是说,会尽可能去寻找最长的能够匹配的子串,此时[go.......................ms]显然是能够匹配的最长子串。
而如果要满足我的需求,则应该选择使用勉强型匹配,也叫最小匹配。它的写法是,在需要最小串长就匹配成功的地方,加上?。在此例中,我们希望'['在一遇到"]["出就匹配,而最后也要尽快匹配']',故,我们要这么写:
Pattern pattern="\\[.+?\\]\\[.+?\\]";
这两个问号就是我们希望尽快匹配的位置,所以后来我选择了这种方式成功输出了结果。

那java中还有一种占有型匹配是怎么回事呢?它的写法是,在你希望要尽可能多匹配的位置加上一个+,它和贪婪型的区别在于,贪婪型在尝试匹配尽量多的字符时,一旦发现最终无法满足要求,它是会回溯的,重新寻找,直至找到(详细算法我暂时还没看源码,但不影响我们掌握它的思路),当然如果实在没有也没办法。而占有型则是,当遇到pattern中使用+来表示要占有匹配时,它就尽可能的和源字符串进行匹配,直至无法继续,然后在去匹配正则式中下面的部分,如果下面的部分无法匹配,此时是不会像最大匹配那样回溯的。find(),match() 都会返回false。举个直观的例子吧:
Pattern pattern_tanlan="\\w+\\w";
Pattern pattern_zhanyou="\\w++\\w";
以上分别是贪婪型和占有型,面对这样的源字符串:“This is [google][1],this is [apple][2],and this is [ms][3].”贪婪型可以成功find出:“This”,"is","google","this","is","apple","and","this","is","ms"这些子串,而占有型则一个也没有。因为匹配\\w时,它们都是尽量往后匹配,以This为例,都匹配到了字母s,可是空格就无法匹配了,然后pattern_tanlan后头的\\w无法匹配,它就回溯,最终让后一个\\w匹配s,而\\w+匹配Thi,但是占有型则不,它不回溯,也就一个也匹配不成了。


0 0
原创粉丝点击