貪婪與非貪婪模式的匹配原理分析

正則表達(dá)式的兩個(gè)普適性原則:

1、優(yōu)先選擇最左側(cè)的匹配結(jié)果

2、標(biāo)準(zhǔn)的匹配量詞是匹配優(yōu)先的

第一條什么意思捏? 就是拿到一個(gè)表達(dá)式/bo/ 去匹配一個(gè)字符串a(chǎn)bsdboosd , 首先這個(gè)表達(dá)式只有一個(gè)可能,那就是真的匹配到bo這兩個(gè)字母,所以直接拿bo 匹配前兩個(gè)字母,匹配不成功,右移,匹配bs 不成功繼續(xù)右移,直到成功匹配或者字符串結(jié)束。

正則表達(dá)式的貪婪模式匹配規(guī)則:

首先要知道正則表達(dá)式中的量詞有:

?【問(wèn)號(hào)】 .【點(diǎn)號(hào)】 *【星號(hào)】 +【加號(hào)】 {min,max} 【集合表達(dá)式】

這幾種量詞都是默認(rèn)盡可能多的去匹配內(nèi)容的,即貪婪模式。當(dāng)然這個(gè)還是會(huì)遵循第一條左側(cè)優(yōu)先的原則的, 比如說(shuō) /no*/ 去匹配 asnosdfanooooosdf 結(jié)果會(huì)是左邊的no 而不是右邊的nooooo

輸入字符串: hai,!xiaozhang! can you tell !me! your qq ?

匹配規(guī)則: /!.+!/

那么匹配的時(shí)候, 第一個(gè)匹配規(guī)則的!, 那么從字符串的0位開(kāi)始匹配,匹配到第一個(gè)感嘆號(hào)時(shí)達(dá)成匹配。

image.jpeg

然后匹配控制權(quán)右移交給點(diǎn)號(hào),于是開(kāi)始匹配 .(點(diǎn)符號(hào)),點(diǎn)符號(hào)匹配換行符以外的任何字符,所以會(huì)一直匹配到最后的問(wèn)號(hào)。

image.jpeg

點(diǎn)加號(hào)匹配就結(jié)束了,開(kāi)始匹配最后一個(gè)感嘆號(hào),因?yàn)橐呀?jīng)到了結(jié)尾,所以匹配開(kāi)始回溯,也就是交出一部分已經(jīng)匹配的字符,以滿足匹配到最右面的感嘆號(hào),一直匹配到 me后面的感嘆號(hào),發(fā)現(xiàn)符合規(guī)則,于是返回最后的匹配結(jié)果:

image.jpeg

------------------------------------------分割線-------------------------------------------------

正則匹配的非貪婪模式的匹配規(guī)則: 【忽略優(yōu)化量詞】

非貪婪模式 / 忽略優(yōu)化量詞,即在量詞后面跟一個(gè)問(wèn)號(hào),分別有 ?? , *? ,+? , {m,n}?, {m,}? 這5種。這些詞在可匹配可不匹配的情況下只選擇不匹配,只有當(dāng)整個(gè)表達(dá)式都無(wú)法匹配成功時(shí)才會(huì)嘗試匹配這些量詞前面的表達(dá)式。

以?? 來(lái)分析:

正則表達(dá)式為 /ab??c/

字符串為: abc

那么匹配的一個(gè)原理是: 先來(lái)到正則表達(dá)式的a

image.jpeg

ok匹配成功,然后匹配權(quán)后移來(lái)到b, b后面有兩個(gè)問(wèn)號(hào), 所以是非貪婪模式, b?? 應(yīng)視為一個(gè)整體來(lái)看。 也就是匹配權(quán)交給 b?? , 這個(gè)時(shí)候會(huì)先忽略匹配,同時(shí)記錄一個(gè)備選狀態(tài),匹配權(quán)交給c ,這時(shí)候規(guī)則c匹配到字母b ,也就是整個(gè)字符串不符合匹配規(guī)則,這個(gè)時(shí)候進(jìn)行回溯, 找到備選狀態(tài),用b?? 來(lái)嘗試匹配字母b,發(fā)現(xiàn)匹配成功,然后匹配權(quán)再次交給c,c去匹配c,ok的,全部匹配成功。結(jié)束匹配。

那么用 /ab??c/ 去匹配asdabcac 是什么結(jié)果呢?

當(dāng)然也是只有一個(gè)abc 。 因?yàn)樵诓婚_(kāi)啟循環(huán)全局搜索的情況下,會(huì)優(yōu)先匹配最左側(cè)的結(jié)果 即普適性原則一 。

那么問(wèn)題又來(lái)了。 用 /e??s/去匹配teset 會(huì)得出什么結(jié)果呢?

會(huì)得到一個(gè)es, 從上面的推理就可以得到,e?? 首先得到匹配權(quán)利,發(fā)現(xiàn)可以忽略,于是進(jìn)入備選狀態(tài),匹配權(quán)交給s,s去匹配t,匹配不通過(guò),取回備選狀態(tài)采用e去匹配t 依舊不匹配,于是字符串右移到第二位也就是字母e,這時(shí)候重新匹配,e??還是會(huì)被優(yōu)先忽略(同時(shí)計(jì)入備選狀態(tài)),匹配權(quán)交給s,s無(wú)法匹配e,于是取回最近的備選狀態(tài)。也就是e去匹配e這時(shí)候匹配成功,然后匹配權(quán)交給s,s去匹配s 成功,整個(gè)匹配結(jié)束,返回結(jié)果es。

其實(shí)這種記錄備選狀態(tài)再取回的方式叫做: 回溯

(回溯在正則里面有個(gè)坑: 災(zāi)難性回溯catastrophic backtracking 詳情可以了解專題文章: 災(zāi)難性回溯)

那么問(wèn)題又來(lái)了,用 /e??se??/ 去匹配 teset 去出現(xiàn)什么結(jié)果呢?

我們還是從頭分析,首先控制權(quán)交給e?? 發(fā)現(xiàn)這個(gè)是忽略優(yōu)先,所以放入備選1,然后控制權(quán)交給s, s去匹配t,失敗,此時(shí)不會(huì)后移控制權(quán),以為s是必須匹配項(xiàng),如果s不匹配后面的都匹配也沒(méi)有意義。所以取回匹配備選項(xiàng)1,e?? 去匹配t,失敗,于是字符串后移,e??再次重新拿到控制權(quán),再次忽略,放入備選狀態(tài)2,控制權(quán)交給s, s去匹配e,失敗,取回備選項(xiàng)2,e??去匹配e 成功,控制權(quán)交給s,s去匹配s成功,匹配權(quán)交給最后的e?? 發(fā)現(xiàn)是忽略優(yōu)先,所以有限選擇忽略,控制權(quán)右移(就結(jié)束了)所以整個(gè)匹配過(guò)程結(jié)束,匹配結(jié)果為es。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容