什么是正則表達(dá)式的貪婪模式和非貪婪模式己单?
我們先從例子入手:
var str = 'a "witch" and her "boom" is one';
str.match(/".*"/g);
原本想要匹配的字符為"witch"
和"broom"
兩個(gè)字符串,運(yùn)行以上的例子看看運(yùn)行結(jié)果:
發(fā)現(xiàn)匹配的是
"witch" and her "broom"
這個(gè)字符串,之所以出現(xiàn)這個(gè)結(jié)果,是因?yàn)檎齽t表達(dá)式的貪婪模式在起作用鳞陨。
查找算法
我們假設(shè)自己是正則引擎厦滤,模擬一下搜索實(shí)現(xiàn)的過程。
正則引擎先從字符串的第0位開始搜索趟咆。
- 第一個(gè)查找字符是
"
,正則在第三位匹配到了它:
- 引擎嘗試匹配正則的剩余部分,第二個(gè)字符是
.
,它代表任意字符庶近。隱藏匹配到了w
:
-
.
代表任意字符重復(fù)一次到多次沙热,因此正則引擎匹配到所有字符:
- 當(dāng)文本結(jié)束后投队,點(diǎn)的匹配停止了息楔,但任然有剩余的正則需要匹配值依,即:
"
愿险,因此,正則引擎開始倒過來回溯扮叨,換句話說,就是一個(gè)字符一個(gè)字符縮減匹配。
當(dāng)匹配縮減后,它開始嘗試匹配剩余的正則扯夭,但"
沒有匹配上字符e
交洗。 - 因此正則繼續(xù)縮減
.
所重復(fù)的字符构拳,再繼續(xù)嘗試:
引號"
沒有匹配上n
斗埂,又失敗了,繼續(xù)嘗試匹配行贪。。缕贡。 - 正則引擎繼續(xù)回溯晾咪,一次一次縮減
.
重復(fù)的字符個(gè)數(shù)谍倦,直到剩余的正則都匹配上:
現(xiàn)在"
終于匹配上了圆存。如果正則是global
的夫植,正則引擎會從上次匹配結(jié)果之后繼續(xù)查找更多結(jié)果详民。
由上面的例子可以看出,在貪婪(默認(rèn))模式下谒出,正則引擎盡可能多的重復(fù)匹配字符
非貪婪模式
非貪婪模式和貪婪模式相反,可通過在代表數(shù)量的標(biāo)示符后放置?
來開啟非貪婪模式,如?
贰镣、+?
甚至是??
恭陡。
可以看到劫狠,這次匹配到了
"witch"
和"broom"
独泞。接下來看看非貪婪模式
.?
是怎樣運(yùn)轉(zhuǎn)的
- 第一步和上面類似懦砂,引號
"
被匹配上:
- 第二步罚随,
.
被匹配上:
- 下面是兩者的重要區(qū)別削罩。正則引擎嘗試用最小可能的重復(fù)次數(shù)來進(jìn)行匹配进陡,因此在
.
匹配了w
后趾疚,它立即嘗試"
的匹配:
沒有匹配上,因?yàn)?code>i!="魄缚。 -
.
重復(fù)更多的字符冶匹,在進(jìn)行嘗試:
又匹配上袒餐,繼續(xù)匿乃。泄隔。佛嬉。 -
終于匹配上了:
- 因?yàn)檎齽t是
global
的,所以正則引擎繼續(xù)后面的匹配,從引號后面的a
字符開始库物。后面又匹配到第二個(gè)字符串:
常見量次符:
? 問號表示某個(gè)模式出現(xiàn)0次或1次撵枢,等同于{0,1}靴姿。
* 星號表示某個(gè)模式出現(xiàn)0次或多次空猜,等同于{0,}搜贤。
+ 加號表示某個(gè)模式出現(xiàn)1次或多次仪芒,等同于{1,}。
總結(jié):通過上面的兩個(gè)例子哟沫,我們發(fā)現(xiàn)一些量詞符在默認(rèn)情況下都是最大可能的匹配猾警,即匹配直到下一個(gè)字符不滿足匹配規(guī)則為止,這就是貪婪模式穴墅。要想匹配到非貪婪模式可以在量詞后面加一個(gè)問號玄货。