正则之贪婪和非贪婪(惰性)模式

前言

阅读此文章之前建议先了解常用正则特殊字符

  • 贪婪模式的量词,也叫匹配优先量词,包括:
    “?”、“*”、“+”、“{n,}”、“{n,m}”
  • 非贪婪模式的量词,也叫忽略优先量词(匹配优先量词后加“?”),包括:
    “??”、“*?”、“+?”、“{n,}?”、“{n,m}?”

概述

贪婪模式和非贪婪模式影响的是被量词修饰的子表达式的行为,贪婪模式是在整个表达式匹配成功的前提下尽可能多的匹配,非贪婪模式则是在整个表达式匹配成功的前提下尽可能少的匹配。非贪婪模式只被部分NFA引擎所支持。

参照以下例子来简单认识下贪婪和非贪婪模式下不同的匹配结果:
示例字符串:“<div><img src=”http://guoweitang.net/1.jpg”><img src=”http://guoweitang.net/2.jpg”></div>”

  • 贪婪模式:/\bsrc=".+"/
    匹配结果:src="http://guoweitang.net/1.jpg"&gt;&lt;img src="http://guoweitang.net/2.jpg"
  • 非贪婪模式:/\bsrc=".+?"/
    匹配结果:src="http://guoweitang.net/1.jpg"

匹配原理

NFA匹配原理参考正则基础之——NFA引擎匹配原理

贪婪模式

源字符串:”Regex”
正则表达式:”.*”

下面我们看一下匹配过程:

  1. 首先由第一个“””取得控制权,匹配位置0位的“””,匹配成功,控制权交给“.*”。
  2. “.*”取得控制权后,由于“*”是匹配优先量词,在可匹配可不匹配的情况下,优先尝试匹配。从位置1处的“R”开始尝试匹配,匹配成功,继续向右匹配,直到匹配到结尾的“””,匹配成功,由于此时已匹配到字符串的结尾,所以“.*”结束匹配,将控制权交给正则表达式最后的“””。
  3. “””取得控制权后,由于已经在字符串结束位置,匹配失败,向前查找可供回溯的状态,控制权交给“.*”,由“.*”让出一个字符,也就是字符串结尾处的“””,再把控制权交给正则表达式最后的“””,由“””匹配字符串结尾处的“””,匹配成功。

此时整个正则表达式匹配成功,其中“.*”匹配的内容为“Regex”,匹配过程中进行了一次回溯。

非贪婪模式

源字符串:”Regex”
正则表达式:”.*?”
这里写图片描述
下面我们看一下匹配过程:

  1. 首先由第一个“””取得控制权,匹配位置0位的“””,匹配成功,控制权交给“.*?”。
  2. “.*?”取得控制权后,由于“*?”是忽略优先量词,在可匹配可不匹配的情况下,优先尝试不匹配。从位置1处尝试忽略匹配,也就是不匹配任何内容,将控制权交给正则表达式最后的“””。
  3. “””取得控制权后,从位置1处尝试匹配,由“””匹配位置1处的“R”,匹配失败,向前查找可供回溯的状态,控制权交给“.*?”,由“.*?”匹配一个字符,匹配位置1处的“R”,再把控制权交给正则表达式最后的“””。
  4. “””取得控制权后,从位置2处尝试匹配,由“””匹配位置1处的“e”,匹配失败,向前查找可供回溯的状态,重复以上过程,直到由“.*?”匹配到“x”为止,再把控制权交给正则表达式最后的“””。
  5. “””取得控制权后,从位置6处尝试匹配,由“””匹配字符串最后的“””,匹配成功。

此时整个正则表达式匹配成功,其中“.*?”匹配的内容为“Regex”,匹配过程中进行了五次回溯。

匹配效率

从以上匹配过程看来,贪婪模式比非贪婪模式进行了更少的回溯,也就是更有效率,那是否贪婪模式逗比非贪婪模式效率更高呢,答案是否定的,如果贪婪模式匹配到了过多匹配结果不需要的内容时会进行更多的回溯,所以它们之间的效率没有绝对,要根据实际情况进行选择。

还有一个事实就是,非贪婪模式可以实现的,通过优化量词修饰的子表达式的贪婪模式都可以实现;而贪婪模式可以实现的,非贪婪模式不一定能实现。

贪婪模式效率提升

可以通过固化分组占有优先量词来提升贪婪模式的匹配效率,非贪婪模式没有这一功能。
.NET中可以使用固化分组,Java中可以使用占有优先量词。

精通正则表达式七:占有优先量词和固化分组

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值