正則表達式的先行斷言(lookahead)和後行斷言(lookbehind)(轉)

正則表達式的先行斷言(lookahead)和後行斷言(lookbehind)(轉)

正則表達式的先行斷言和後行斷言一共有4種形式:
(?=pattern) 零寬正向先行斷言(zero-width positive lookahead assertion)
(?!pattern) 零寬負向先行斷言(zero-width negative lookahead assertion)
(?<=pattern) 零寬正向後行斷言(zero-width positive lookbehind assertion)
(?<!pattern) 零寬負向後行斷言(zero-width negative lookbehind assertion)
這裏面的pattern是一個正則表達式。

如同^代表開頭,$代表結尾,\b代表單詞邊界一樣,先行斷言和後行斷言也有類似的作用,它們只匹配某些位置,在匹配過程中,不佔用字符,所以被稱爲“零寬”。所謂位置,是指字符串中(每行)第一個字符的左邊、最後一個字符的右邊以及相鄰字符的中間(假設文字方向是頭左尾右)。
下面分別舉例來說明這4種斷言的含義。

(?=pattern) 正向先行斷言
代表字符串中的一個位置,緊接該位置之後的字符序列能夠匹配pattern。
例如對”a regular expression”這個字符串,要想匹配regular中的re,但不能匹配expression中的re,可以用”re(?=gular)”,該表達式限定了re右邊的位置,這個位置之後是gular,但並不消耗gular這些字符,將表達式改爲”re(?=gular).”,將會匹配reg,元字符.匹配了g,括號這一砣匹配了e和g之間的位置。

(?!pattern) 負向先行斷言
代表字符串中的一個位置,緊接該位置之後的字符序列不能匹配pattern。
例如對”regex represents regular expression”這個字符串,要想匹配除regex和regular之外的re,可以用”re(?!g)”,該表達式限定了re右邊的位置,這個位置後面不是字符g。負向和正向的區別,就在於該位置之後的字符能否匹配括號中的表達式。

(?<=pattern) 正向後行斷言
代表字符串中的一個位置,緊接該位置之前的字符序列能夠匹配pattern。
例如對”regex represents regular expression”這個字符串,有4個單詞,要想匹配單詞內部的re,但不匹配單詞開頭的re,可以用”(?<=\w)re”,單詞內部的re,在re前面應該是一個單詞字符。之所以叫後行斷言,是因爲正則表達式引擎在匹配字符串和表達式時,是從前向後逐個掃描字符串中的字符,並判斷是否與表達式符合,當在表達式中遇到該斷言時,正則表達式引擎需要往字符串前端檢測已掃描過的字符,相對於掃描方向是向後的。

(?<!pattern) 負向後行斷言
代表字符串中的一個位置,緊接該位置之前的字符序列不能匹配pattern。
例如對”regex represents regular expression”這個字符串,要想匹配單詞開頭的re,可以用”(?<!\w)re”。單詞開頭的re,在本例中,也就是指不在單詞內部的re,即re前面不是單詞字符。當然也可以用”\bre”來匹配。

對於這4個斷言的理解,可以從兩個方面入手:
1.關於先行(lookahead)和後行(lookbehind):正則表達式引擎在執行字符串和表達式匹配時,會從頭到尾(從前到後)連續掃描字符串中的字符,設想有一個掃描指針指向字符邊界處並隨匹配過程移動。先行斷言,是當掃描指針位於某處時,引擎會嘗試匹配指針還未掃過的字符,先於指針到達該字符,故稱爲先行。後行斷言,引擎會嘗試匹配指針已掃過的字符,後於指針到達該字符,故稱爲後行。
2.關於正向(positive)和負向(negative):正向就表示匹配括號中的表達式,負向表示不匹配。

對這4個斷言形式的記憶:
1.先行和後行:後行斷言(?<=pattern)、(?<!pattern)中,有個小於號,同時也是箭頭,對於自左至右的文本方向,這個箭頭是指向後的,這也比較符合我們的習慣。把小於號去掉,就是先行斷言。
2.正向和負向:不等於(!=)、邏輯非(!)都是用!號來表示,所以有!號的形式表示不匹配、負向;將!號換成=號,就表示匹配、正向。

發佈了39 篇原創文章 · 獲贊 6 · 訪問量 5855
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章