正则表达式学习笔记(二)表达式的匹配原理

表达式的匹配原理

一)正则引擎的分类

1.DFA(符合或者不符合POSIX标准的都属于此类):电动机

2.传统NFA: 传统的汽油机

3.POSIX NFA:符合新标准的汽油机

二)两条规则

规则1:优先选择最左端的匹配结果

匹配先从需要查找的字符串的起始位置尝试匹配,即从第一个字符开始测试整个正则表达式,如果测试了所有

可能后仍然找不到结果,则从第二个字符开始测试,直到找到结果。

例如:

1.用'ORA'来匹配FLOARAL,从字符串左边开始的第一轮匹配会失败(因为ORA不能匹配FLO),同理

第二轮也会失败,第三轮成功。

2.用'cat'来匹配:

The dragging belly indicates that your cat is too fat.

匹配结果是indicates中的cat

3.用'fat|cat|belly|your'匹配2中的句子,结果是?

注意:锚点直接匹配位置。

规则2: 标准量词是匹配优先的

标准匹配量词:?,*,+,{min, max}

如果用这些量词来约束某个表达式,例如'(tang)*'中的'tang', 'a?'中的'a',在匹配成功之前,进行尝试的次数是存在上限和下限的

规则2表明这些尝试总是希望获得最长的匹配。它们总是尝试匹配尽可能多的字符串,直到匹配上限为止。

例如:用'[0-9]+'匹配'TangJia19900326'能匹配字符串中的所有数字,这是因为1匹配成功之后,已经满足了匹配

成功的下限了,但此时正则表达式是匹配优先的,所以它会继续匹配完所有的数字。

过度的匹配优先:

'^.*([0-9](0-9))'匹配过程:由于标准量词优先原则,'.*'会直接匹配完整行,此时'([0-9][0-9])在尝试匹配时会失败,这样它就会强迫'.*'交出

一些字符供自己匹配,但这种‘强迫’是建立在不破坏'.*'匹配成功的条件之上的。

例如,用上述表达式匹配'about a 25 girl chen','.*'匹配整个字符穿后,第一个'[0-9]'的匹配要求'.*'释放一个字符'n',但这并不能让'[0-9]'

匹配,所以必须继续交还字符'e',直到释放'5'。但不幸的是第一个'[0-9]'虽然匹配成功了,第二个'[0-9]'仍然不能匹配。为了匹配整个

正则表达式,此时必须释放'2'(给第一个匹配),第二个'[0-9]'开始匹配,并最后成功匹配到'5'。

思考:用'^.*([0-9]+)'来匹配'tang 2003'   括号会捕获到什么?

三)表达式主导和文本主导

 NFA引擎:表达式主导

例如:用表达式'to(nite|knight|night)'匹配'...tonight...',表达式第一个元素是't',它将会重复尝试,

直到在目标字符串中找到't',找到后再在目标字符串中查找'o',找到后会在目标元素中依次尝试'nite','knight',

'night'三种可能匹配成功。尝试'nite'的过程和之前一样,一个字符一个字符地依次尝试。

DFA引擎:文本主导

回溯(Backtracking)

基本原理----略。两个重要原则:

1.对于匹配优先量词,会进行尝试,对于忽略优先量词,会跳过尝试

2.后进先出

 忽略优先量词

用'<B>.*?</B>'来匹配:

<B>Billions</B> and <B>Zillions</B> of suns......

开始匹配'<B>'之后,'.*?'首先决定不匹配任何字符,因为他是忽略优先的。

于是控制权交给后面的'<'符号,此时遇到了字符串中的B无法匹配,控制权

交还给'.*?',表达式便匹配到了B,因为是忽略优先的,控制权再次交给'<',

在重复数次后,最终匹配到: ‘<B>Billions</B>’

但如果我们用该表达式匹配: ‘<B>Billions<B> and <B>Zillions</B> of suns......’

就会匹配到:‘<B>Billions<B> and <B>Zillions</B’,这不是我们想要的结果

我们可以用否定环视解决这个问题:

 

 

 固化分组:(?>......)

使用'(?>......)'的匹配与正常匹配的差别在于,如果匹配进行到结构结束后(也就是闭括号之后),结构体中的所有备用状态都将会被抛弃。

例子: '(\.\d\d(?>[1-9]?))\d+'在固化分组内,量词能够正常工作,如果'[1-9]'不能匹配,正则表达式则会返回'?'留下的备用状态。

然后脱离固化分组,继续前进到'\d+'。在这种状态下,当控制权离开固化分组时,没有备用状态需要放弃。

 占有优先量词: ?+、 *+、 ++、 和{m,n}+

占有优先量词和匹配优先量词的差别:不交还已经匹配的字符。

环视中的回溯

多选结构也是匹配优先的吗?

1.对于大多数传统型NFA:按顺序匹配,前面的匹配成功就不尝试后面的。

2.少数DFA和POSIX NFA:匹配优先,尽可能匹配更多的字符。

 四)NFA、DFA 和 POSIX

最左最长规则

NFA:按顺序来

DFA:匹配最长的

posted @ 2018-09-19 15:44  Shadowplay  阅读(222)  评论(0编辑  收藏  举报