ditunes / blog

write my idea & share my tunes
1 stars 1 forks source link

正则表达式匹配原理 #5

Open ditunes opened 8 years ago

ditunes commented 8 years ago

正则表达式的匹配原理

正则中的量词

标准量词是匹配优先

? {min,max}都是匹配优先

忽略优先量词

+? *? ?? 只尽量少匹配符合要求的字符,先执行忽略。除非下一个表达式无法匹配字符发生回溯的时候才执行匹配。

占有优先量词和固化分组

总的而言在匹配位置离开占有优先或固化分组表达式的时候其备用状态将给予清除,如正则表达式(?>.+) 它属于匹配优先,备用状态栈中会存放多个备用状态(即表达式下一个位置和文本中执行与当前表达式匹配的位置)。一旦成为固化分组,则栈内所有备用状态都将被清除。占有优先量词也是类似(?>.+)(.)++. 放弃备用状态会产生什么影响呢?

1465969436704

多选结构下的正则匹配流程

有如下正则表达式:a(b|c|d)X 匹配的文本:abM ,_记录了当前表达式or文本的匹配位置。

当正则表达式中的'a'匹配到文本中的'a'之后,正则表达式出现匹配分支即遇可能匹配 b or c or d ,此时将会把可能匹配的备用状态入栈,备用状态、初始状态如下:

1465972714198

引擎继续向前运行,当表达式b和文本'b'匹配上后,a(b|c|d)_X | ab_M接下来就是表达式X与文本的M匹配,因为表达式没有匹配分支,则直接匹配,此时出现不匹配则需要回溯,即备用状态栈出栈,再执行匹配而事实上这次匹配又一次失败 1465976153703

以此类推,继续出栈此时匹配仍然失败,那么备用状态栈中已经为空了,此时我们需要变更初始状态了,即将文本_abM转变为a_bM重新执行表达式匹配。

1465976647232

依据此规律直到初始状态为abM_备用状态栈为空,且表达式依然没有全局匹配成功,则表示表达式与文本匹配失败。

回溯与匹配优先、忽略优先

匹配优先的本质是在表达式出现匹配分支的时候优先选择匹配量词最大值进行匹配,而把匹配量词最小值情况放入备用状态栈中。那么忽略优先的情形则是将量词最大值放入备用状态栈中,匹配量词最小值直接进行匹配。我们可以通过*+元字符来理解

如正则表达式:^.+[0-9][0-9]文本 abc 123456 abc; 由于.+表示匹配优先,则其会尽力匹配足够多的文本内容。而只匹配一个的情况会成为备用状态。当前正要执行文本c与表达式.+的匹配

1466058827376

如正则表达式:^.*[0-9][0-9]文本 abc 123456 abc; 由于.*表示匹配优先,则其会尽力匹配足够多的文本内容。而忽略的情况会成为备用状态。当前正要执行文本c与表达式.+的匹配 1466058927971

*+的差别无非就是*遇到文本字符时候就出现匹配分支(更多 or 忽略)而+匹配文本字符成功后才出现匹配分支(更多 or end)