正则表达式之匹配优先与忽略优先

正则表达式之匹配优先与忽略优先

概述

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

标准匹配量词(?、*、+,以及{min,max})都是“匹配优先(greedy)”的。如果用这些量词来约束某个表达式,例如‘a?’中的‘a’,‘[0-9]+’中的‘[0-9]’,在匹配成功之前,进行尝试的次数是存在上限和下限的。标准匹配量词的结果“可能”并非所有可能中最长的,但它们总是尝试匹配尽可能多的字符,直到匹配上限为止。

而忽略优先,则是在原本的匹配优先量词后加一个问号即可,即在*、+、?、{min,max}后加入?即可。

匹配优先:尽可能多的匹配
忽略优先:尽可能少的匹配

要注意的是,DFA不支持忽略优先。

匹配优先量词:*、+、?、{min,max}
忽略优先量词:*?、+?、??、{min,max}?

1.匹配优先:

我们来看‘^\w+\d’匹配‘1a2b2c2de’的过程。首先‘\w+’匹配整个字符串之后,然后为了匹配‘\d’要求‘\w+’释放一个字符‘e’(最后的字符)。看是否能让‘\d’匹配,如果不能匹配,‘\w+’必须继续“交还”字符,直到能匹配‘\d’为止,如果所有的字符都交还完后还是不能匹配,则匹配失败。
在这里插入图片描述

2.忽略优先:

而对于忽略优先,总是匹配尽可能少的字符,先用‘\w’来匹配‘1a2b2c2de’中的‘1’,此时,‘+?’又必须选择,是继续进行匹配,还是忽略?因为它是忽略优先的,会首先选择忽略。接下来的‘\d’不能匹配后面的‘a’,所以‘\w+?’会继续尝试未匹配的‘a’,然后看后面的字符能否匹配‘\d’,直到能匹配‘\d’或尝试所有可能后报告匹配失败。
在这里插入图片描述

3.如果用‘^\w+(\d+)’和‘^\w+?(\d+)’来匹配‘copyright2019’,括号会捕获到什么?

‘^\w+(\d+)’匹配时为了满足‘\d+’的匹配,必须交还一些字符。释放的字符是最后的‘9’,之后‘9’能够由‘\d’匹配。‘\d’由‘+’量词进行修饰,所以现在还做到了最小匹配的可能,此时没有“必须”匹配的元素,所以‘\w’不会被迫交出‘1’。匹配优先的结构只会在被迫的情况下交还字符。所以,最终$1的值是‘9’:
在这里插入图片描述
‘^\w+?(\d+)’匹配时会先匹配‘copyright2019’中的‘c’,因为它是忽略优先的,会首先选择忽略,接下来‘\d’不能匹配后一个字符‘o’,所以‘\w+’会继续匹配未匹配的‘o’,在这个过程重复9次之后,‘\w+’最终匹配了‘copyright’,此时,接下来的‘2019’都能匹配,所以最终$1的值是‘2019’:
在这里插入图片描述

4.对于匹配双引号文本:

首先想到的可能就是‘ “.*” ’,在最开始的双引号匹配之后,‘.*’能够匹配任何字符,所以它会一直匹配到字符串的末尾。为了让最后的双引号能够匹配,‘.*’不会交还字符(或者更确切的说,是正则引擎强迫它回退),直到满足为止。最后,这个正则表达式的结果就是:
在这里插入图片描述
原本希望匹配到的是"McDonald’s"和"makudonarudo",然而这显然不是我们所期望的结果,我们希望匹配到的不是双引号之间的“任何文本”,而是“除双引号以外的任何文本”。如果用‘[^"]*’替代‘.*’,结果是:
在这里插入图片描述
用排除法时注意,因为在大多数的流派中,‘[^"]*’能够匹配换行符,而点号则不能。
在这里插入图片描述
如果不想让表达式匹配换行符,可以用‘[^"\n]’。在这里插入图片描述
也可以使用忽略优先量词:
在这里插入图片描述

5.对于多字符“引文”

与双引号字符的例子一样,使用“.*”匹配多字符引文也会出错,‘<B>.*</B>’中匹配优先‘.*’会一直匹配到该行的结尾字符,回溯只会进行到最后一个‘</B>’,而不是与匹配开头的‘<B>’相对应的‘</B>’:
在这里插入图片描述
我们可以使用忽略优先量词‘<B>.*?</B>’来进行匹配:
在这里插入图片描述
当然,错误的使用忽略优先量词有时候也会出现问题,如果用‘<B>.*?</B>’来匹配‘…<B>Billions and <B> Zillions</B> of suns…’时会出现:
在这里插入图片描述
显然这不是用户所期望的结果,这时候如果支持否定环视,我们就能得到与排除型字符组相当的结果,只有当‘<B>’不在字符串中的当前位置才能匹配成功。
在这里插入图片描述
这时候不管是用匹配优先量词还是忽略优先量词都可以。

测试链接

https://regexr.com/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值