作為開始,我們先看下面的正則:
var str = 'a "witch" and her "broom" is one';
str.match( /".*"/g);
我們本來預(yù)想上面會(huì)匹配得到"witch"
和"broom"
兩個(gè)字符串忍燥,運(yùn)行上面的例子拧晕,卻發(fā)現(xiàn)結(jié)果只匹配到"witch" and her "broom"
一個(gè)字符串。
之所以出現(xiàn)這個(gè)結(jié)局梅垄,是因?yàn)檎齽t的貪婪模式在起作用厂捞。
一输玷、貪婪模式(默認(rèn))
首先我們假設(shè)自己是正則引擎,來模擬搜索實(shí)現(xiàn)的過程靡馁。
正則引擎先從字符串的第0位開始搜索欲鹏。
- 第一個(gè)查找字符是
"
,正則引擎在第三個(gè)位置匹配到了它:
-
之后臭墨,引擎嘗試匹配正則的剩余部分赔嚎,第二個(gè)字符是
.
,它代表任意字符。引擎匹配到了w
:尋找任意字符. -
.
代表任意字符重復(fù)一次到多次胧弛,因此正則引擎匹配到所有字符一直尋找到最后 -
當(dāng)文本結(jié)束后尤误,點(diǎn)的匹配停止了,但仍然有剩余的正則
"
需要匹配结缚,因此正則引擎開始倒過來回溯损晤,換句話說,就是一個(gè)字符一個(gè)字符縮減匹配红竭。找到最后了尤勋,但最后的字符不是",又要從后往前找"當(dāng)匹配縮減后茵宪,它開始嘗試匹配剩余的正則最冰,但
"
沒有匹配上字符e
。 因此正則繼續(xù)縮減
.
所重復(fù)的字符稀火,繼續(xù)嘗試锌奴。
-
正則引擎回溯,一次一次縮減
.
重復(fù)的字符個(gè)數(shù)憾股,直到剩余的正則都匹配上:從后往前終于找到"了 現(xiàn)在
"
終于匹配上了鹿蜀。 如果正則是global
的,正則引擎會(huì)從上次匹配結(jié)果之后繼續(xù)查找更多結(jié)果服球。
總結(jié):在貪婪(默認(rèn))模式下茴恰,正則引擎盡可能多的重復(fù)匹配字符。
二斩熊、非貪婪模式
非貪婪模式和貪婪模式相反往枣,可通過在代表數(shù)量的標(biāo)識(shí)符后放置?
來開啟非貪婪模式,如?
粉渠、+?
甚至是??
分冈。
var str = 'a "witch" and her "broom" is one';
str.match(/".*?"/g ) // "witch", "broom"
我們來看看非貪婪模式.?
是怎么運(yùn)轉(zhuǎn)的:
-
第一步和上面類似,引號(hào)
"
被匹配上尋找字符串" -
第二步也一樣霸株, '.'被匹配上
尋找任意字符. -
下面是二者的重要區(qū)別雕沉。 正則引擎嘗試用最小可能的重復(fù)次數(shù)來進(jìn)行匹配,因此在
.
匹配了w
后去件,它立即嘗試"
的匹配找到.后繼續(xù)找"可惜沒有匹配上坡椒,因?yàn)?code>t!="扰路。
-
.
重復(fù)更多的字符,再進(jìn)行嘗試往后尋找"又沒匹配上倔叼,繼續(xù)~~
-
下面終于匹配上了
找到"了汗唱, 后面可能還有,繼續(xù)找 -
因?yàn)檎齽t是
global
的丈攒,所以正則引擎繼續(xù)后面的匹配哩罪,從引號(hào)后面的a
字符開始,后面又匹配到第二個(gè)字符串就這樣找到更多的"
總結(jié):在非貪婪模式下巡验,正則引擎盡可能少的重復(fù)匹配字符际插。