日期:2014-05-20  浏览次数:21396 次

【分享】正则基础之——贪婪与非贪婪模式
1 概述
贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。非贪婪模式只被部分NFA引擎所支持。
属于贪婪模式的量词,也叫做匹配优先量词,包括:
“{m,n}”、“{m,}”、“?”、“*”和“+”。
在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”,即变成属于非贪婪模式的量词,也叫做忽略优先量词,包括:
“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。
从正则语法的角度来讲,被匹配优先量词修饰的子表达式使用的就是贪婪模式,如“(Expression)+”;被忽略优先量词修饰的子表达式使用的就是非贪婪模式,如“(Expression)+?”。
对于贪婪模式,各种文档的叫法基本一致,但是对于非贪婪模式,有的叫懒惰模式或惰性模式,有的叫勉强模式,其实叫什么无所谓,只要掌握原理和用法,能够运用自如也就是了。个人习惯使用贪婪与非贪婪的叫法,所以文中都会使用这种叫法进行介绍。


由于篇幅较长,且很多解释依靠颜色区分,样式及链接等在帖子里编辑不方便,具体内容还是到我的博客去看吧。
正则基础之——贪婪与非贪婪模式


声明一:本帖不是散分帖,只对找出错误,提供改进建议,进行技术讨论,阅读后给出个人见解的回复给分,其余回复不给分,请尽量看过帖子后再回复。

声明二:本帖主要偏重匹配原理及匹配效率分析,属于基础知识点的介绍,对于绝大多数使用NFA引擎的语言都通用,所以没有多少应用实例讲解,如果对正则感兴趣,可以先收起来慢慢看^_^

------解决方案--------------------
这种贴一定要顶起来:
个人认为:反向引用,零宽断言也很重要....
------解决方案--------------------
在捕获组这篇中:
HTML code
举例:替换掉html标签中的属性。

<textarea id="result" rows="10" cols="100"></textarea> <script type="text/javascript"> var data = "<table id=\"test\"><tr class=\"light\"><td> test </td></tr></table>";var reg = /<([a-z]+)[^>]*>/ig;document.getElementById("result").value = data.replace(reg, "<$1>");</script>//输出<table><tr><td> test </td></tr></table>

------解决方案--------------------
各种正则表达式语法比较:
http://hi.baidu.com/wuchangqian/blog/item/68e142de4fefa51a495403d6.html
------解决方案--------------------
我认为该把 4.2.2 忽略优先量词的匹配下限
放到开始的地方一起写了而不是在后面来单独写,不知道的话,看了前面就疑惑不已。

还有就是图不用画还好些,举点简单例子大家能看懂哦。反而被你说复杂了。不必去深入的去追究匹配过程,熟了自然知道,看了反而晕。

纯属个人看法。
------解决方案--------------------
感觉正则挺好用,但是逻辑性挺强的 用好还真不容易 !
lz说的贪婪和非贪婪模式小弟已经收藏,拜读一下
------解决方案--------------------
固化分组这个东西不宜太过渲染,否则当转用其他的语言去实现的时候,会有很多莫名其妙的感觉。
就像我在javascript中使用零宽断言的时候,一直不知道出了什么问题,后面才发现是javascript不支持。

以前也研究过一段时间的正则表达式,不过没你的系统和理论化,学习了。
http://blog.csdn.net/zhiqiangzhan/archive/2009/10/12/4659534.aspx

------解决方案--------------------
举例:

需求:取得两个“””中的子串,其中不能再包含“””。

正则表达式一:”.*”

正则表达式二:”.*?”

情况一:当贪婪模式匹配到更多不需要的内容时,可能存在比非贪婪模式更多的回溯。比如源字符串为“The word “Regex” means regular expression.”。

情况二:贪婪模式无法满足需求。比如源字符串为“The phrase "regular expression" is called "Regex" for short.”。

报告客客,这2个正则错误。
------解决方案--------------------
探讨
源字符串:aa<div>test1</div>bb<div>test2</div>cc
正则表达式二:<div>.*?</div>
匹配结果二:<div>test1</div>

...

由于采用的是非贪婪模式,所以结束匹配,不再向右尝试,匹配结果为“<div>test1</div>”。

...

通俗点讲,就是找到一个想要的捡起来就行了,至于还有没有没捡的就不管了

------解决方案--------------------
<div>test1</div>bb<div>test2</div>cc

对于这个我想匹配得到结果为<div>test2</div>cc 该用什么表达式?意思就是匹配后面为cc的div标签的内容,我尝试用<div>.*?</div>(?=cc),可是仍旧无效