正則表達(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á)成匹配。

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

點(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é)果:

------------------------------------------分割線-------------------------------------------------
正則匹配的非貪婪模式的匹配規(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

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。