15年来,为全国50万+企业提供互联网数字化基础应用服务。
知 识
0514-86177077
9:00-17:00(工作日)
首 页
企业400电话
Hot
网站☯建设
微网小程序
商标✡知产
网络营销推广
AI电话机器人
热
彩铃©短信
增值拓展业务
新
主页
>
知识库
> 正则表达式之 贪婪与非贪婪模式详解(概述)
正则表达式之 贪婪与非贪婪模式详解(概述)
热门标签:
浙江营销外呼系统有哪些
哈尔滨公司外呼系统代理
惠安地图标注
山东外呼系统联系方式
自己做的电销机器人
上海销售电销机器人软件
辽宁秒客来电话机器人
地图标注店铺地图标注酒店
淄博市张店区地图标注
1 概述
贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。非贪婪模式只被部分NFA引擎所支持。
属于贪婪模式的量词,也叫做匹配优先量词,包括:
“{m,n}”、“{m,}”、“?”、“*”和“+”。
在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”,即变成属于非贪婪模式的量词,也叫做忽略优先量词,包括:
“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。
从正则语法的角度来讲,被匹配优先量词修饰的子表达式使用的就是贪婪模式,如“(Expression)+”;被忽略优先量词修饰的子表达式使用的就是非贪婪模式,如“(Expression)+?”。
对于贪婪模式,各种文档的叫法基本一致,但是对于非贪婪模式,有的叫懒惰模式或惰性模式,有的叫勉强模式,其实叫什么无所谓,只要掌握原理和用法,能够运用自如也就是了。个人习惯使用贪婪与非贪婪的叫法,所以文中都会使用这种叫法进行介绍。
2 贪婪与非贪婪模式匹配原理
对于贪婪与非贪婪模式,可以从应用和原理两个角度进行理解,但如果想真正掌握,还是要从匹配原理来理解的。
先从应用的角度,回答一下“什么是贪婪与非贪婪模式?”
2.1 从应用角度分析贪婪与非贪婪模式
2.1.1 什么是贪婪与非贪婪模式
先看一个例子
举例:
源字符串:aadiv>test1/div>bbdiv>test2/div>cc
正则表达式一:div>.*/div>
匹配结果一:div>test1/div>bbdiv>test2/div>
正则表达式二:div>.*?/div>
匹配结果二:div>test1/div>(这里指的是一次匹配结果,所以没包括div>test2/div>)
根据上面的例子,从匹配行为上分析一下,什是贪婪与非贪婪模式。
正则表达式一采用的是贪婪模式,在匹配到第一个“/div>”时已经可以使整个表达式匹配成功,但是由于采用的是贪婪模式,所以仍然要向右尝试匹配,查看是否还有更长的可以成功匹配的子串,匹配到第二个“/div>”后,向右再没有可以成功匹配的子串,匹配结束,匹配结果为“div>test1/div>bbdiv>test2/div>”。当然,实际的匹配过程并不是这样的,后面的匹配原理会详细介绍。
仅从应用角度分析,可以这样认为,贪婪模式,就是在整个表达式匹配成功的前提下,尽可能多的匹配,也就是所谓的“贪婪”,通俗点讲,就是看到想要的,有多少就捡多少,除非再也没有想要的了。
正则表达式二采用的是非贪婪模式,在匹配到第一个“/div>”时使整个表达式匹配成功,由于采用的是非贪婪模式,所以结束匹配,不再向右尝试,匹配结果为“div>test1/div>”。
仅从应用角度分析,可以这样认为,非贪婪模式,就是在整个表达式匹配成功的前提下,尽可能少的匹配,也就是所谓的“非贪婪”,通俗点讲,就是找到一个想要的捡起来就行了,至于还有没有没捡的就不管了。
2.1.2 关于前提条件的说明
在上面从应用角度分析贪婪与非贪婪模式时,一直提到的一个前提条件就是“整个表达式匹配成功”,为什么要强调这个前提,我们看下下面的例子。
正则表达式三:div>.*/div>bb
匹配结果三:div>test1/div>bb
修饰“.”的仍然是匹配优先量词“*”,所以这里还是贪婪模式,前面的“div>.*/div>”仍然可以匹配到“div>test1/div>bbdiv>test2/div>”,但是由于后面的“bb”无法匹配成功,这时“div>.*/div>”必须让出已匹配的“bbdiv>test2/div>”,以使整个表达式匹配成功。这时整个表达式匹配的结果为“div>test1/div>bb”,“div>.*/div>”匹配的内容为“div>test1/div>”。可以看到,在“整个表达式匹配成功”的前提下,贪婪模式才真正的影响着子表达式的匹配行为,如果整个表达式匹配失败,贪婪模式只会影响匹配过程,对匹配结果的影响无从谈起。
非贪婪模式也存在同样的问题,来看下面的例子。
正则表达式四:div>.*?/div>cc
匹配结果四:div>test1/div>bbdiv>test2/div>cc
这里采用的是非贪婪模式,前面的“div>.*?/div>”仍然是匹配到“div>test1/div>”为止,此时后面的“cc”无法匹配成功,要求“div>.*?/div>”必须继续向右尝试匹配,直到匹配内容为“div>test1/div>bbdiv>test2/div>”时,后面的“cc”才能匹配成功,整个表达式匹配成功,匹配的内容为“div>test1/div>bbdiv>test2/div>cc”,其中“div>.*?/div>”匹配的内容为“div>test1/div>bbdiv>test2/div>”。可以看到,在“整个表达式匹配成功”的前提下,非贪婪模式才真正的影响着子表达式的匹配行为,如果整个表达式匹配失败,非贪婪模式无法影响子表达式的匹配行为。
2.1.3 贪婪还是非贪婪——应用的抉择
通过应用角度的分析,已基本了解了贪婪与非贪婪模式的特性,那么在实际应用中,究竟是选择贪婪模式,还是非贪婪模式呢,这要根据需求来确定。
对于一些简单的需求,比如源字符为“aadiv>test1/div>bb”,那么取得div标签,使用贪婪与非贪婪模式都可以取得想要的结果,使用哪一种或许关系不大。
但是就2.1.1中的例子来说,实际应用中,一般一次只需要取得一个配对出现的div标签,也就是非贪婪模式匹配到的内容,贪婪模式所匹配到的内容通常并不是我们所需要的。
那为什么还要有贪婪模式的存在呢,从应用角度很难给出满意的解答了,这就需要从匹配原理的角度去分析贪婪与非贪婪模式。
2.2 从匹配原理角度分析贪婪与非贪婪模式
如果想真正了解什么是贪婪模式,什么是非贪婪模式,分别在什么情况下使用,各自的效率如何,那就不能仅仅从应用角度分析,而要充分了解贪婪与非贪婪模式的匹配原理。
2.2.1 从基本匹配原理谈起
NFA引擎基本匹配原理参考:正则基础之——NFA引擎匹配原理。
这里主要针对贪婪与非贪婪模式涉及到的匹配原理进行介绍。先看一下贪婪模式简单的匹配过程。
源字符串:"Regex"
正则表达式:".*"
图2-1
注:为了能够看清晰匹配过程,上面的空隙留得较大,实际源字符串为“”Regex””,下同。
来看一下匹配过程。首先由第一个“"”取得控制权,匹配位置0位的“"”,匹配成功,控制权交给“.*”。
“.*”取得控制权后,由于“*”是匹配优先量词,在可匹配可不匹配的情况下,优先尝试匹配。从位置1处的“R”开始尝试匹配,匹配成功,继续向右匹配,匹配位置2处的“e”,匹配成功,继续向右匹配,直到匹配到结尾的“””,匹配成功,由于此时已匹配到字符串的结尾,所以“.*”结束匹配,将控制权交给正则表达式最后的“"”。
“"”取得控制权后,由于已经在字符串结束位置,匹配失败,向前查找可供回溯的状态,控制权交给“.*”,由“.*”让出一个字符,也就是字符串结尾处的“””,再把控制权交给正则表达式最后的“"”,由“"”匹配字符串结尾处的“"”,匹配成功。
此时整个正则表达式匹配成功,其中“.*”匹配的内容为“Regex”,匹配过程中进行了一次回溯。
接下来看一下非贪婪模式简单的匹配过程。
源字符串:"Regex"
正则表达式:".*?"
图2-2
看一下非贪婪模式的匹配过程。首先由第一个“"”取得控制权,匹配位置0位的“"”,匹配成功,控制权交给“.*?”。
“.*?”取得控制权后,由于“*?”是忽略优先量词,在可匹配可不匹配的情况下,优先尝试不匹配,由于“*”等价于“{0,}”,所以在忽略优先的情况下,可以不匹配任何内容。从位置1处尝试忽略匹配,也就是不匹配任何内容,将控制权交给正则表达式最后的“””。
“"”取得控制权后,从位置1处尝试匹配,由“"”匹配位置1处的“R”,匹配失败,向前查找可供回溯的状态,控制权交给“.*?”,由“.*?”吃进一个字符,匹配位置1处的“R”,再把控制权交给正则表达式最后的“"”。
“"”取得控制权后,从位置2处尝试匹配,由“"”匹配位置1处的“e”,匹配失败,向前查找可供回溯的状态,重复以上过程,直到由“.*?”匹配到“x”为止,再把控制权交给正则表达式最后的“"”。
“"”取得控制权后,从位置6处尝试匹配,由“"”匹配字符串最后的“"”,匹配成功。
此时整个正则表达式匹配成功,其中“.*?”匹配的内容为“Regex”,匹配过程中进行了五次回溯。
2.2.2 贪婪还是非贪婪——匹配效率的抉择
通过匹配原理的分析,可以看到,在匹配成功的情况下,贪婪模式进行了更少的回溯,而回溯的过程,需要进行控制权的交接,让出已匹配内容或匹配未匹配内容,并重新尝试匹配,在很大程度上降低匹配效率,所以贪婪模式与非贪婪模式相比,存在匹配效率上的优势。
但2.2.1中的例子,仅仅是一个简单的应用,读者看到这里时,是否会存在这样的疑问,贪婪模式就一定比非贪婪模式匹配效率高吗?答案是否定的。
举例:
需求:取得两个“"”中的子串,其中不能再包含“"”。
正则表达式一:".*"
正则表达式二:".*?"
情况一:当贪婪模式匹配到更多不需要的内容时,可能存在比非贪婪模式更多的回溯。比如源字符串为“The word "Regex" means regular expression.”。
情况二:贪婪模式无法满足需求。比如源字符串为“The phrase "regular expression" is called "Regex" for short.”。
对于情况一,正则表达式一采用的贪婪模式,“.*”会一直匹配到字符串结束位置,控制权交给最后的“””,匹配不成功后,再进行回溯,由于多匹配的内容“means regular expression.”远远超过需匹配内容本身,所以采用正则表达式一时,匹配效率会比使用正则表达式二的非贪婪模式低。
对于情况二,正则表达式一匹配到的是“"regular expression" is called "Regex"”,连需求都不满足,自然也谈不上什么匹配效率的高低了。
以上两种情况是普遍存在的,那么是不是为了满足需求,又兼顾效率,就只能使用非贪婪模式了呢?当然不是,根据实际情况,变更匹配优先量词修饰的子表达式,不但可以满足需求,还可以提高匹配效率。
源字符串:"Regex"
给出正则表达式三:"[^"]*"
看一下正则表达式三的匹配过程。
图2-3
首先由第一个“"”取得控制权,匹配位置0位的“"”,匹配成功,控制权交给“[^"]*”。
“[^"]*”取得控制权后,由于“*”是匹配优先量词,在可匹配可不匹配的情况下,优先尝试匹配。从位置1处的“R”开始尝试匹配,匹配成功,继续向右匹配,匹配位置2处的“e”,匹配成功,继续向右匹配,直到匹配到“x”,匹配成功,再匹配结尾的“””时,匹配失败,将控制权交给正则表达式最后的“"”。
“””取得控制权后,匹配字符串结尾处的“””,匹配成功。
此时整个正则表达式匹配成功,其中“[^"]*”匹配的内容为“Regex”,匹配过程中没有进行回溯。
将量词修饰的子表达式由范围较大的“.”,换成了排除型字符组“[^"]”,使用的仍是贪婪模式,很完美的解决了需求和效率问题。当然,由于这一匹配过程没有进行回溯,所以也不需要记录回溯状态,这样就可以使用固化分组,对正则做进一步的优化。
给出正则表达式四:"(?>[^"]*)"
固化分组并不是所有语言都支持的,如.NET支持,而Java就不支持,但是在Java中却可以使用更简单的占有优先量词来代替:"[^"]*+"。
3 贪婪还是非贪婪模式——再谈匹配效率
一般来说,贪婪与非贪婪模式,如果量词修饰的子表达式相同,比如“.*”和“.*?”,它们的应用场景通常是不同的,所以效率上一般不具有可比性。
而对于改变量词修饰的子表达式,以满足需求时,比如把“.*”改为“[^"]*”,由于修饰的子表达式已不同,也不具有直接的可对比性。但是在相同的子表达式,又都可以满足需求的情况下,比如“[^"]*”和“[^"]*?”,贪婪模式的匹配效率通常要高些。
同时还有一个事实就是,非贪婪模式可以实现的,通过优化量词修饰的子表达式的贪婪模式都可以实现,而贪婪模式可以实现的一些优化效果,却未必是非贪婪模式可以实现的。
贪婪模式还有一点优势,就是在匹配失败时,贪婪模式可以更快速的报告失败,从而提升匹配效率。下面将全面考察贪婪与非贪婪模式的匹配效率。
3.1 效率提升——演进过程
在了解了贪婪与非贪婪模式的匹配基本原理之后,我们再来重新看一下正则效率提升的演进过程。
需求:取得两个“"”中的子串,其中不能再包含“"”。
源字符串:The phrase "regular expression" is called "Regex" for short.
正则表达式一:".*"
正则表达式一匹配的内容为“"regular expression" is called "Regex"”,不符合要求。
提出正则表达式二:".*?"
首先“"”取得控制权,由位置0位开始尝试匹配,直到位置11处匹配成功,控制权交给“.*?”,匹配过程同2.2.1中非贪婪模式的匹配过程。“.*?”匹配的内容为“Regex”,匹配过程中进行了四次回溯。
如何消除回溯带来的匹配效率的损失,就是使用更小范围的子表达式,采用贪婪模式,提出正则表达式三:"[^"]*"
首先“"”取得控制权,由位置0位开始尝试匹配,直到位置11处匹配成功,控制权交给“[^"]*”,匹配过程同2.2.2节中非贪婪模式的匹配过程。“[^"]*”匹配的内容为“Regex”,匹配过程中没有进行回溯。
3.2 效率提升——更快的报告失败
以上讨论的是匹配成功的演进过程,而对于一个正则表达式,在匹配失败的情况下,如果能够以最快的速度报告匹配失败,也会提升匹配效率,这或许是我们设计正则过程中最容易忽略的。而在源字符串数据量非常大,或正则表达式比较复杂的情况下,是否能够快速报告匹配失败,将对匹配效率产生直接的影响。
下面将构建匹配失败的正则表达式,对匹配过程进行分析。
以下匹配过程分析中,源字符串统一为:The phrase "regular expression" is called "Regex" for short.
3.2.1 非贪婪模式匹配失败过程分析
图3-1
构建匹配失败的非贪婪模式的正则表达式:".*?"@
由于最后的“@”的存在,这个正则表达式最后一定是匹配失败的,那么看一下匹配过程。
首先由“"”取得控制权,由位置0处开始尝试匹配,匹配失败,直到图中标示的A处匹配成功,控制权交给“.*?”。
“.*?”取得控制权后,由A后面的位置开始尝试匹配,由于是非贪婪模式,首先忽略匹配,将控制权交给“"”,同时记录一下回溯状态。“"”取得控制权后,由A后面的位置开始尝试匹配,匹配字符“r”失败,查找可供回溯的状态,将控制权交给“.*?”,由“.*?”匹配字符“r”。重复以上过程,直到“.*?”匹配了B处前面的字符“n”,“"”匹配了B处的字符“””,将控制权交给“@”。由“@”匹配接下来的空格“ ”,匹配失败,查找可供回溯的状态,控制权交给“.*?”,由“.*?”匹配空格。继续重复以上匹配过程,直到由“.*?”匹配到字符串结束位置,将控制权交给“"”。由于已经是字符串结束位置,匹配失败,报告整个表达式在位置11处匹配失败,一轮匹配尝试结束。
正则引擎传动装置使正则向前传动,进入下一轮尝试。后续匹配过程与第一轮尝试匹配过程基本类似,可以参考图3-1。
从匹配过程中可以看到,非贪婪模式的匹配失败过程,几乎每一步都伴随着回溯过程,对匹配效率的影响是很大的。
3.2.2 贪婪模式匹配失败过程分析——大范围子表达式
图3-2
PS:以上分析过程图示参考了《精通正则表达式》一书相关章节图示。
构建匹配失败的贪婪模式的正则表达式:".*"@
其中量词修饰的子表达式为匹配范围较大的“.”,由于最后的“@”的存在,这个正则表达式最后也是一定匹配失败的,看一下匹配过程。
首先由“"”取得控制权,由位置0处开始尝试匹配,匹配失败,直到图中标示的A处匹配成功,控制权交给“.*”。
“.*”取得控制权后,由A后面的位置开始尝试匹配,由于是贪婪模式,优化尝试匹配,一直匹配到字符串的结束位置,将控制权交给“"”。“"”取得控制权后,由于已经是字符串的结束位置,匹配失败,查找可供回溯的状态,将控制权交给“.*”,由“.*”让出已匹配字符“.”。重复以上过程,直到后面“"”匹配了C处后面的字符“””,将控制权交给“@”。由“@”匹配接下来D处的空格“ ”,匹配失败,查找可供回溯的状态,控制权交给“.*”,由“.*”让出已匹配文本。继续重复以上匹配过程,直到由“.*”让出所有已匹配的文本到I处,将控制权交给“"”。“"”匹配失败,由于已经没有可供回溯的状态,报告整个表达式在位置11处匹配失败,一轮匹配尝试结束。
正则引擎传动装置使正则向前传动,进入下一轮尝试。后续匹配过程与第一轮尝试匹配过程基本类似,可以参考图3-2。
从匹配过程中可以看到,大范围子表达式贪婪模式的匹配失败过程,从总体上看,与非贪婪模式没有什么区别,最终进行的回溯次数与非贪婪模式基本一致,对匹配效率的影响仍然很大。
3.2.3 贪婪模式匹配失败过程分析——改进的子表达式
图3-3
构建匹配失败的贪婪模式的正则表达式:"[^"]*"@
其中量词修饰的子表达式,改为匹配范围较小的排除型字符组“[^"]”,由于最后的“@”的存在,这个正则表达式最后也是一定匹配失败的,看一下匹配过程。
首先由“"”取得控制权,由位置0处开始尝试匹配,匹配失败,直到图中标示的A处匹配成功,控制权交给“[^"]*”。
“[^"]*”取得控制权后,由A后面的位置开始尝试匹配,由于是贪婪模式,优先尝试匹配,一直匹配到B处,将控制权交给“"”。“"”匹配接下来的的字符“"”,匹配成功,将控制权交给“@”。由“@”匹配接下来的空格“ ”,匹配失败,查找可供回溯的状态,控制权交给“[^"]*”,由“[^"]*”让出已匹配文本。继续重复以上匹配过程,直到由“[^"]*”让出所有已匹配的文本到C处,将控制权交给“"”。“"”匹配失败,由于已经没有可供回溯的状态,报告整个表达式在位置11处匹配失败,一轮匹配尝试结束。
正则引擎传动装置使正则向前传动,进入下一轮尝试。后续匹配过程与第一轮尝试匹配过程基本类似,可以参考图3-3。
从匹配过程中可以看到,使用了排除型字符组的贪婪模式的匹配失败过程,从总体上看,大量减少了每轮回溯的次数,可以有效的提升匹配效率。
3.2.4 贪婪模式匹配失败过程分析——固化分组
通过3.2.3节的分析可以知道,由于“[^"]*”使用了排除型字符组,那么图3-3中,在A和B之间被匹配到的字符,就一定不会是字符“"”,所以B到C之间回溯过程就是多余的,也就是说在这之间的可供回溯的状态完全可以不记录。.NET中可以使用固化分组,Java中可以使用占有优先量词来实现这一效果。
图3-4
首先由“"”取得控制权,由位置0处开始尝试匹配,匹配失败,直到图中标示的A处匹配成功,控制权交给“(?>[^"]*)”。
“(?>[^"]*)”取得控制权后,由A后面的位置开始尝试匹配,由于是贪婪模式,优先尝试匹配,一直匹配到B处,将控制权交给“"”,在这一匹配过程中,不记录任何可供回溯的状态。“"”匹配接下来的字符“””,匹配成功,将控制权交给“@”。由“@”匹配接下来的空格“ ”,匹配失败,查找可供回溯的状态,由于已经没有可供回溯的状态,报告整个表达式在位置11处匹配失败,一轮匹配尝试结束。
正则引擎传动装置使正则向前传动,进入下一轮尝试。后续匹配过程与第一轮尝试匹配过程基本类似,可以参考图3-4。
从匹配过程中可以看到,使用了固化分组的贪婪模式的匹配失败过程,没有涉及到回溯,可以最大限度的提升匹配效率。
3.3 非贪婪模式向贪婪模式的转换
使用匹配范围较大的子表达式时,贪婪模式与非贪婪模式匹配到的内容会有所不同,但是通过优化子表达式,非贪婪模式可以实现的匹配,贪婪模式都可以实现。
比如在实际应用中,匹配img标签的内容。
举例:
需求:取得img标签中的图片地址,src=后固定为“””
源字符串:img class="test" src="/img/logo.gif" title="测试" />
正则表达式一:img\b.*?src="(.*?)".*?>
匹配结果中,捕获组1的内容即为图片地址。可以看到,这个例子中使用的都是非贪婪模式,而根据上面章节的分析,后面两个非贪婪模式都可以使用排除型字符组,将非贪婪模式转换为贪婪模式。
正则表达式二:img\b.*?src="([^"]*)"[^>]*>
注:“src="…"”和标签结束标记符“>”之间的属性中,也可能出现字符“>”,但那是极端情况,这里不予讨论。
后两处非贪婪模式,可以通过排除型字符组转换为贪婪模式,提高匹配效率,而“src=”前的非贪婪模式,由于要排除的是一个字符序列“src=”,而不是单独的某一个或几个字符,所以不能使用排除型字符组。当然也不是没有办法,可以使用顺序环视来达到这一效果。
正则表达式三:img\b(?:(?!src=).)*src="([^"]*)"[^>]*>
“(?!src=).”表示这样一个字符,从它开始,右侧不能是字符序列“src=”,而“(?:(?!src=).)*”就表示符合上面规则的字符,有0个或无限多个。这样就达到排除字符序列的目的,实现的效果同排除型字符组一样,只不过排除型字符组排除的是一个或多个字符,而这种环视结构排除的是一个或多个有序的字符序列。
但是以顺序环视的方式排除字符序列,由于在匹配每一个字符时,都要进行较多的判断,所以相对于非贪婪模式,是提升效率还是降低效率,要根据实际情况进行分析。对于简单的正则表达式,或是简单的源字符串,一般来说是非贪婪模式效率高些,而对于数量较大源字符串,或是复杂的正则表达式,一般来说是贪婪模式效率高些。
比如上面取得img标签中的图片地址需求,基本上用正则表达二就可以了;对于复杂的应用,如平衡组中,就需要使用结合环视的贪婪模式了。
以匹配嵌套div标签的平衡组为例:
Regex reg = new Regex(@"(?isx) #匹配模式,忽略大小写,“.”匹配任意字符
div[^>]*> #开始标记“div...>”
(?> #分组构造,用来限定量词“*”修饰范围
div[^>]*> (?Open>) #命名捕获组,遇到开始标记,入栈,Open计数加1
| #分支结构
/div> (?-Open>) #狭义平衡组,遇到结束标记,出栈,Open计数减1
| #分支结构
(?:(?!/?div\b).)* #右侧不为开始或结束标记的任意字符
)* #以上子串出现0次或任意多次
(?(Open)(?!)) #判断是否还有'OPEN',有则说明不配对,什么都不匹配
/div> #结束标记“/div>”
");
“(?:(?!/?div\b).)*”这里使用的就是结合环视的贪婪模式,虽然每匹一个字符都要做很多判断,但这种判断是基于字符的,速度很快,而如果这里使用非贪婪模式,那么每次要做的就是分支结构“|”的判断了,而分支结构是非常影响匹配效率的,其代价远远高于对确定字符的判断。而另外一个原因,就是贪婪模式可以结合固化分组来提升效率,而对非贪婪模式使用固化分组却是没有意义的。
4 贪婪与非贪婪——最后的回顾
4.1 一个例子的匹配原理回顾
再回过头来看一下2.1.1节例子中正则,前面从应用角度进行了分析,但讨论过匹配原理后会发现,匹配过程并不是那么简单的,下面从匹配原理角度分析的匹配过程。
图4-1
首先由“”取得控制权,由位置0位开始尝试匹配,匹配字符“a”,匹配失败,第一轮匹配结束。第二轮匹配从位置1开始尝试匹配,同样匹配失败。第三轮从位置3开始尝试匹配,匹配字符“”,匹配成功,控制权交给“d”。
“d”尝试匹配字符“d”,匹配成功,控制权交给“i”。重复以上过程,直到由“>”匹配到字符“>”,控制权交给“.*”。
“.*”属于贪婪模式,将从B处后的字符“t”开始,一直匹配到E处,也就是字符串结束位置,将控制权交给“”。
“”从字符串结束位置尝试匹配,匹配失败,向前查找可供回溯的状态,把控制权交给“.*”,由“.*”让出一个字符“c”,把控制权再交给“”,尝试匹配,匹配失败,向前查找可供回溯的状态。一直重复以上过程,直到“.*”让出已匹配的字符“”,实际上也就是让出了已匹配的子串“/div>cc”为止,“”才匹配字符“”成功,控制权交给“/”。
接下来由“/”、“d”、“i”、“v”分别匹配对应的字符成功,此时整个正则表达式匹配完毕。
4.2 贪婪与非贪婪——量词的细节
4.2.1 区间量词的非贪婪模式
前面提到的非贪婪模式,一直都是使用的“*?”,而没有涉及到其它的区间量词,对于“*?”和“+?”这样的非贪婪模式,大多数接触过正则表达式的人都可以理解,但是对于区间量词的非贪婪模式,比如“{m,n}?”,要么是没见过,要么是不理解,主要是这种应用场景非常少,所以被忽略了。
首先需要明确的一点,就是量词“{m,n}”是匹配优先量词,虽然它有了上限,但是在达到上限之前,能够匹配,还是要尽可能多的匹配的。而“{m,n}?”就是对应的忽略优先量词了,在可匹配可不匹配的情况下,尽可能少的匹配。
接下来举一个例子说明这种非贪婪模式的应用。
举例(参考 限制字符长度与最小匹配):
需求:如何限制在长度为100的字符串中,从头匹配到最先出现的abc
csdn.{1,100}abc 这样写是最大匹配(1-100个字符串中,我需要最小的)
比如csdnfddabckjdsfjabc,匹配结果应为:csdnfddabc
正则表达式:csdn.{1,100}?abc
或许对这个例子还有人不是很理解,但是想想,其实“*”就等价于“{0,}”,“+”就等价于“{1,}”,“*?”也就是“{0,}?”,抽象出来也就是“{m,}?”,即上限为无穷大。如果上限为一个固定值,那就是“{m,n}?”,这样应该也就可以理解了。
“{m}”没有放在匹配优先量词中,同样的,“{m}?”虽然被部分语言所支持,但是也没有放在忽略优先量词中,主要是因为这两种量词,实现的效果是一样的,只有被修饰的子表达式匹配m次才能匹配成功,且没有可供回溯的状态,所以也不存在是匹配优先还是忽略优先的问题,也就不在本文的讨论范围内。事实上即使讨论也没有意义的,只要知道它们的匹配行为也就是了。
4.2.2 忽略优先量词的匹配下限
对于匹配优先量词的匹配下限很好理解,“?”等价于“{0,1}”,它修饰的子表达式,最少匹配0次,最多匹配1次;“*”等价于“{0,}”,它修饰的子表达式,最少匹配0次,最多匹配无穷多次;“+”等价于“{1,}”,它修饰的子表达式,最少匹配1次,最多匹配无穷多次。
对于忽略优先量词的下限,也是容易忽略的。
“??”也是忽略优先量词,被修饰的子表达式使用的也是非贪婪模式,“??”修饰的子表达式,最少匹配0次,最多匹配1次。在匹配过程中,遵循非贪婪模式匹配原则,先不匹配,即匹配0次,记录回溯状态,只有不得不匹配时,才去尝试匹配。
“*?”修饰的子表达式,最少匹配0次,最多匹配无穷多次;“+?”修饰的子表达式,最少匹配1次,最多匹配无穷多次,“+?”虽然使用的是非贪婪模式,在匹配过程中,首先要匹配一个字符,之后才是忽略匹配的,这一点也需要注意。
4.3 贪婪与非贪婪模式小结
Ø 从语法角度看贪婪与非贪婪
被匹配优先量词修饰的子表达式,使用的是贪婪模式;被忽略优先量词修饰的子表达式,使用的是非贪婪模式。
匹配优先量词包括:“{m,n}”、“{m,}”、“?”、“*”和“+”。
忽略优先量词包括:“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。
Ø 从应用角度看贪婪与非贪婪
贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配;而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。非贪婪模式只被部分NFA引擎所支持。
Ø 从匹配原理角度看贪婪与非贪婪
能达到同样匹配结果的贪婪与非贪婪模式,通常是贪婪模式的匹配效率较高。
所有的非贪婪模式,都可以通过修改量词修饰的子表达式,转换为贪婪模式。
贪婪模式可以与固化分组结合,提升匹配效率,而非贪婪模式却不可以。
您可能感兴趣的文章:
正则表达式(regex) 贪婪模式、懒惰模式使用方法
小议正则表达式效率 贪婪、非贪婪与回溯
浅谈php正则表达式中的非贪婪模式匹配的使用
[正则表达式]贪婪模式与非贪婪模式
正则表达式量词与贪婪的使用详解
标签:
长沙
铜川
西安
宣城
重庆
泰州
绵阳
无锡
巨人网络通讯声明:本文标题《正则表达式之 贪婪与非贪婪模式详解(概述)》,本文关键词 正则,表达式,之,贪婪,与,;如发现本文内容存在版权问题,烦请提供相关信息告之我们,我们将及时沟通与处理。本站内容系统采集于网络,涉及言论、版权与本站无关。
相关文章
下面列出与本文章《正则表达式之 贪婪与非贪婪模式详解(概述)》相关的同类信息!
正则表达式之 贪婪与非贪婪模式详解(概述)
1 概述 贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可...
10-18
400电话特点400电话申请以后有什么使用功能?
具有400电话,本身便是企业的一个标志,在长期应用400电话作为服务客服号码的时分,让客户在对产品进行咨询,以及在售后...
01-13
湖南电销卡是什么意思(电销卡正规吗)
本文目录一览:1、电销卡是如何产生的?2、什么是电话销售卡3、电费自助缴费终端哪家好电销卡是如何产生的? 1、电销卡其...
07-10
青岛人工外呼系统公司(电话人工外呼)
本文目次一览: 1、青岛门萨维智能呆板人技术无限公司怎样样? 2、青岛德律风体系 3、此刻外呼体系哪家公司做的对照好?...
11-25
ai电话机器人营销服务方案(智能营销电话机器人)
本文目录一览:1、智能客服机器人在在线客服领域的应用有哪些?2、各大电话机器人有什么特点吗3、关于电销机器人4、电话...
07-06
好分期电话机器人(好分期电话人工客服号码)
今天给各位分享好分期电话机器人的知识,其中也会对好分期电话人工客服号码进行解释,如果能碰巧解决你现在面临的问题...
05-03
青岛电话营销电话卡哪种卡好
青岛电话营销电话卡哪种卡好 电销卡靠谱吗?对许多刚接触过的电销卡的人来说,因为他们对电销卡的知识比较缺乏,也不...
12-16
合肥电销语音机器人稳定吗(智能语音电销机器人平台)
本篇文章给咱们谈谈合肥电销语音机器人安稳吗,以及智能语音电销机器人渠道对应的知识点,期望对各位有所协助,不要忘...
11-06
30人呼叫中心外呼系统(电话外呼系统呼叫中心系统)
本篇文章给大家谈谈30人呼叫中心外呼系统,以及电话外呼系统呼叫中心系统对应的知识点,希望对各位有所帮助,不要忘了...
11-06
广西房产专用AI机器人什么价格-总算知道
广西房产专用AI机器人什么价格而他所采用的呼叫系统也是大数据系统,其中的行业语言也是通过不同的行业进行设定,很多...
05-17
400电话使企业推广更上一层楼
在多变的市场中,我们只有找到对的营销方式,才能为企业打开新的市场局面,而我们都知道一个企业的发展壮大是需要依托...
12-23
福州教育AI电话机器人哪里有,电话群呼系统办理服务商-价格合理
一企嗨电话营销系统 1.当前的电销场景有哪些困扰? 1)手机.卡频繁被封,电销业务难以启动; 2)销售人员号码被标注,...
12-17
江西外呼系统哪家不错(外呼系统哪家性价比高)
今日给各位共享江西外呼体系哪家不错的常识,其间也会对外呼体系哪家性价比高进行解说,假如能可巧处理你现在面对的问...
11-06
洛阳全自动外呼系统供应商(河南智能外呼)
本文目录一览: 1、外呼体系哪家公司做得好???2、想自己做机器人外呼体系,线路,怎样拼装3、外呼体系哪家公司做的好?...
04-23
河南便宜外呼系统厂家(河南智能外呼系统)
本文目次一览: 1、智能德律风外呼体系哪家的对照好用? 2、有靠谱的外呼体系吗,别让我再办卡,公司几百 3、德律风外呼...
11-25
成都电销卡办理-电销卡不封号
成都电销卡办理-电销卡不封号 巨人网络通讯主营企业通信业务,专售电销卡、电销专用卡、不封号电话卡、外呼系统、电销...
06-24
商标转让为什么贵
商标转让的费用主要由两个部门组成, 一部分是商标本身的费用。另外一部分则是商标转让过程中所产生的规费。 而商标转...
10-23
使用电销卡打电销的时候要注意什么
电销这种模式具有成本低等优势,因此许多企业都会有电销模式。但是工信部的相关政策出台之后,普通的卡就不能用来做电...
06-27
PowerShell函数参数设置为即可选又必选的方法
本文介绍PowerShell自定义函数中使用参数集时,可以将同一个参数既设置为可选,又设置为必选。 好吧,小编承认,这个话题...
10-18
2014年退市的科技公司-高德地图标注
2014还未走远,完满国际就打响了2015年私有化的第一枪。2014年敲响纳斯达克钟声的科技公司不少,可郊外的人想进去,城里的...
04-13
400电话申请选择业务的依据
很多的事情,我们在做的过程中,总是要有一些对应的依据,真正的去做好了这个方面的考虑,并且认识到了这些内在的依据...
05-16
电销团队外包信息(电销项目外包)
今日给各位共享电销团队外包信息的常识,其间也会对电销项目外包进行解说,假如能可巧处理你现在面对的问题,别忘了重...
06-17
.Net判断一个对象是否为数值类型实例
本文实例讲述了.Net判断一个对象是否为数值类型的方法,分享给大家供大家参考。具体实现方法如下: .Net判断一个对象是否...
10-18
淘宝店铺如何用分销新模式、新方法创业?
想要利用淘宝分销新模式创业,首先要满足以下几个条件:①拥有淘宝网店分销的资格,得到货源支持。也就是说首先,必须...
12-14
悟空人工智能电话销售机器人厂家合作
传统 电销 被诸多因素制约发展传统电销行业已经被越来越多的因素制约着发展。为实现业绩最大化,企业只能依靠增加更多...
10-31
王传言:服务外包人才培养路在何方
长期以来,服务外包人才短缺问题是制约我国服务外包企业发展的瓶颈。随着世界金融危机阴霾的逐步淡化,中国的服务外包...
10-22
洛克外呼系统(洛克智能外呼)
今天给各位分享洛克外呼系统的知识,其中也会对洛克智能外呼进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本...
11-06
福建智能云外呼系统(厦门外呼系统)
本文目录一览: 1、智能外呼系统是什么?求介绍2、智能外呼系统是什么,请附上操作指南?3、什么叫智能外呼系统?4、智...
11-27
巨人科技成为企业品排的好代言
说起一加好的企业,我们不同的人也许会给出不同的评价标准。那么,总会有一些评价的标准是亘古不变的,能够很好地也系...
05-15
Win8 下.NET Framework 3.5离线安装包无法直接安装
知识点分析: 默认情况下,Windows 8 集成 .NET 4.5 8.1集成 .NET 4.5.1 不包括.NET 3.5 (包括.NET 2.0 和 3.0) 由于系统架构变化.NET 3.5离线...
10-20
awk基础知识小结第1/2页
1、使用规则 awk 适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行需要特殊技巧程序设计。 awk 的语法较为...
10-18
韶关电话机器人有什么优势(什么是电话机器人)
本文目录一览: 1、智能电话机器人的优势是什么?2、电话机器人好用吗,有什么优势?3、电话机器人有哪些优势4、电话机...
11-28
江苏语音电话机器人公司(智能语音电话机器人)
本文目录一览:1、能对话的智能机器人2、ai机器人外呼系统3、我需要一个,自动拨打电话机器人软件能对话的智能机器人 您...
08-28
如何开发智能电话机器人(如何开发智能电话机器人技术)
本篇文章给大家谈谈如何开发智能电话机器人,以及如何开发智能电话机器人技术对应的知识点,希望对各位有所帮助,不要...
05-16
长沙电销机器人费用(长沙电销机器人费用多少钱)
本文目录一览: 1、电话机器人多少钱,哪款比较好?2、电销机器人的作用怎么样?3、任网行电话机器人的本钱怎么样?4、...
04-23
地理标志证明商标、集体商标注册申请所需提交文件目录及说明
1.《商标注册申请书》 委托商标代理机构代理的,还应当附送《商标代理委托书》。 2申请人主体资格证书复印件(需加盖申请...
10-23
电话机器人录音师薪资(录音师一个月多少钱)
本文目录一览: 1、人工智能电话营销机器人究竟能做什么?2、电话机器人一年8000块多,贵吗?3、电话机器人多少钱?贵嘛...
11-28
外呼系统怎么设置拟人化(外呼模式是什么意思)
本篇文章给大家谈谈外呼系统怎么设置拟人化,以及外呼模式是什么意思对应的知识点,希望对各位有所帮助,不要忘了收藏...
05-16
地方高校商标创建的办学特色
在?牛津英语词典?中对品牌商标有这样的定义:品牌商标是证明供应者的一种“去不掉的标识”设计.而这种标识应该是一种显...
10-23
汕头电销防封线路咨询
汕头电销防封线路咨询,汕头电销防封线路下载,汕头电销防封线路办理 电销防封线路 全国套餐可选,外呼次数效率比普通电...
11-14
温州教育外呼线路如何办理,电话营销线路多少钱-查看价格
温州教育外呼线路如何办理,电话营销线路多少钱真正意义上走向智能化的蜕变。人工智能在营销方面的应用模式:以市场产...
12-16
win7下mysql6.x出现中文乱码的完美解决方法
1、在命令行里停止MySQL服务: net stop mysql 2、修改mysql安装目录下的my,ini,将 default-character-set=latin 改为 default-character-set=gbk...
10-18
付费才能玩 微软win10确定全新商业模式
Windows 10是微软的标志性产品,随着时代的变化,Windows授权营收不断下降。无奈之下,微软只好寻找新办法从客户手中榨取更...
10-20
Win10存在很严重的窥探用户隐私行为 绝对的隐私没有了
英国《卫报》导报,不少国外用户抱怨称Windows 10会将个人数据上传给微软,还会将Wi-Fi密码共享给好友,而且微软还会监控用...
10-20
从行为管理到心态管理(下)
心态管理,你准备好了吗? 前不久,某呼叫中心负责培训的人士跟我谈起了苦衷,她说,我们非常重视对员工心理的管理,...
10-22
河北ai外呼电话机器人排名(智能外呼电话机器人)
本文目录一览:1、ai智能机器人外呼系统哪家的好?2、电销系统软件排名3、有哪种比较知名的智能语音外呼4、电销外呼系统...
07-06
电销卡个体户(电销卡个体户怎么注册)
本文目录一览:1、pos机哪里有办理2、怎样申请POS3、电话销售公司,不办理营业执照,会被查到吗4、代办个体工商户营业执照怎...
07-10
电销专用卡哪种好
电销专用卡哪种好 电销卡是高频呼出的白名单卡,是不会被封号的,因为这类卡是添加过白名单,是允许打高频外呼的。不...
12-03
关于办公室植物墙的挑选办法,你知道多少
在大多数情况下,办公室植物墙的作用一般指办公环境添加绿色环境,美观办公环境与净空办公环境;可以缓解我们的工作压...
10-30
中国移动副卡收费 主卡副卡共享(移动副卡资费)
我们在办理手机卡的时候,有的时候想全家共用一个套餐,这样经济又划算,免去了要交很多次手机费,也节省了很多成本,...
11-07
安顺智能ai语音助手
安顺智能ai语音助手 不过这里需要强调的是,我们说的智能电销机器人不是有身体有四肢那种实体存在的机器人,而是一套人...
02-28
正则表达式之 贪婪与非贪婪模式详解(概述)
1 概述 贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可...
10-18
本页收集关于正则表达式之 贪婪与非贪婪模式详解(概述)的相关信息资讯供网民参考!
推荐文章
企业400电话办理要求
一线电话机器人制作贴牌
鹤壁百应电销机器人联系方式
怎么用地图标注距离
赣州语音电销机器人
如何在滴滴上做地图标注
全套地图标注
沈阳400电话申请
太原鹿铃外呼系统
外呼系统要接固话吗
底料行业如何做电销机器人
河南奇手通信外呼系统
湖北地图标注软件
黄冈真人语音电销机器人效果
韶关自建外呼系统
商丘话务外呼系统怎么样
如何在谷歌地图标注并存储
常宁市地图标注
地图标注水流方向吗
辽宁外呼系统哪家好
搜狗地图标注商户中心入驻注册
对中国地图标注不完整的地图
深圳探意电话机器人
地图标注需要现场吗
上海申请400电话哪家强
默纳克系统怎样设外呼
电话自动外呼系统怎么用
广州自动外呼系统业务
山东保险智能外呼系统供应商
宁阳地图标注app
柳州外呼系统有效果吗
西宁电销智能机器人价格
人工电销机器人官网
大地图标注信息
高德地图标注没有我的位置标
性能可靠400电话办理
云界之乱地图标注
微信小程序电子地图标注
导航地图标注位置信息会违法吗
淮北企业外呼系统
贵州高频外呼防封系统
电话机器人与旅游
地图标注苹果和安卓有什么区别
呼来客电话机器人
智能云外呼系统
楼梯间宗地图标注
中国的地图标注在哪里
西安的外呼系统
高德地图标注兴趣点
400电话转接申请
地图标注有什么区别吗
外呼系统的几大因素
黄石防封电销卡
湖南银行智能外呼系统价格
al机器人电销
谷歌地图标注点位
重庆防封电销卡销户流程
天津自动外呼系统收费
郑州呼叫中心外呼系统运营商
携带电话机器人
科特迪瓦地图标注
电销机器人外呼门萨维u
贵州全自动外呼系统供应商
郑州ai电销机器人有效果吗
上海电话机器人视频
五指山市地图标注
吴忠自建外呼系统
电销机器人销量排名
电脑外呼系统平台
太原电话外呼系统
400电话办理哪里便宜
百度地图标注常用位置
电话机器人的号码被拦截
威海自动外呼系统软件
上海电销卡外呼系统如何
无线座机外呼系统
400电话怎么办理停机
外呼系统和法学相关的专业
地图标注补充信息怎么填店标
电话机器人的功能
租外呼线路
杭州人工智能电销机器人价格
外呼系统的好处
默纳克系统外呼一直显示检修
怎么把地图标注导入表格
保山探意电话机器人
中国移动运营商电话机器人
北京400电话办理推选易号网
移动固话带外呼系统吗
天润外呼系统怎么删除录音
清远正规外呼系统厂家
上海010外呼系统
电话销售外呼系统靠谱吗
地图标注各地名烟
广州外呼回拨系统多少钱
怎样跟商家谈地图标注店
外呼系统打电话声音小
外呼系统销售保怎么用
智能营销电话机器人做什么行业好
百度地图标注店名有误
桂林正规电销机器人招商
小信电销展业机器人好用不
地图标注宣传单
电销智能对答机器人销售
电销机器人价位
和田市地图标注
宿迁客服外呼系统
德州语音电销机器人供应商
腾讯地图标注规范
屧魯葒鹶ْ㑴
地图标注用什么app
佛山办理400电话的流程
电销机器人技巧攻略保盈
广州电子地图标注店标
西安400电话办理找哪家
地图标注各门店地址怎么制作
弥勒地图标注
拉萨便宜外呼系统
西方的劫难4地图标注
龙岩市怎样做地图标注
正则表达式之 贪婪与非贪婪模式详解(概述)
上一篇:
正则表达式解二元方程式代码
下一篇:
正则基础之 神奇的转义
一起分享吧
产品关键词: 正则表达式之 贪婪与非贪婪模式详解(概述) 正则,表达式,之,贪婪,与,