java正則表達式特殊構造(非捕獲)

Special constructs (named-capturing and non-capturing)

(?<name>X)   X,as a named-capturing group
(?:X)       X, as a non-capturing group
(?idmsux-idmsux)    Nothing, but turns match flags i d m s u x on -off
(?idmsux-idmsux:X)     X, as a non-capturing group with the given flagsi d m s u x on - off
(?=X)      X, via zero-width positive lookahead
(?!X)       X, via zero-width negative lookahead
(?<=X)   X,via zero-width positive lookbehind
(?<!X)     X, via zero-width negative lookbehind
(?>X)    X, as an independent, non-capturing group

特殊構造(非捕獲)
(?<name>X)   X,作爲命名捕獲組
(?:X)    X,作爲非捕獲組
(?idmsux-idmsux)    Nothing,但是將匹配標誌idmsux on - off
(?idmsux-idmsux:X)     X,作爲帶有給定標誌 i d m s u x on - off
(?=X)    X,通過零寬度的正 lookahead
(?!X)    X,通過零寬度的負 lookahead
(?<=X)    X,通過零寬度的正 lookbehind
(?<!X)      X, 通過零寬度的負 lookbehind
(?>X)    X,作爲獨立的非捕獲組

好傢伙,這文檔寫的,英文不是中文,中文也不是中文。不得不解釋下鳥:


lookahead和lookbehind也就是先行後行。

先行指的是,在進行斷言的時候,字符串匹配引擎指針會被向前移動(向後一個字符移動)以進行斷言(由於zero-width,所以之後會再被移回)。

後行指的是,在進行斷言的時候,字符串匹配引擎指針會被向後移動(向前一個字符移動)以進行斷言(由於zero-width,所以之後會再被移回)。

zero-width也就是零寬度。指的是斷言前後不會改變當前字符串匹配引擎的指針位置。

positive 和negative  表示是預測匹配還是不匹配。

因此:

1 (?=X),預測其前邊字串匹配位置後爲X。

(?=X)的意思就是預測匹配位置之後出現的應該是X。如果符合則匹配上。在(?=X)後邊帶上不以X爲開始的任意字符串都將導致該表達式不能被匹配。因爲預測不改變當前字符串搜索的指針(零寬度)。

例如:

表達式"a(?=b)c"不能匹配"abc",也不能匹配"ac"、"ab"。而且不能匹配任何字符串。因爲其預測匹配a的位置後,應該是b,但是,又要求a之後是c。

表達式"a(?=b)bc"是可以匹配"abc"的,但是不能匹配"ab"和"ac"。


如果(?=X)前沒有字符,則表示在任何位置處(因爲匹配的是任何字串),預測其後是X。

例如:

(?=b)bc 可以匹配“bc"中的bc

(?=b)b可以匹配"bc"中的b

(?=b)可以匹配"bc"中的最開始位置


(?=X)的工作過程如下:

左邊的表達式匹配後,字符串引擎匹配位置右移,然後引擎發現是一個lookahead斷言,因此判斷該位置後是否符合斷言(爲了不改變位置指針,需要斷言後回溯),如果符合,繼續進行匹配。

由於斷言是向前的,所以爲先行;在斷言前後,字符串引擎匹配位置不改變,所以爲零寬度;又因爲是要求預測爲“符合”,因此爲正向;因此稱爲零寬度正向先行斷言

例如,a(?=b)b匹配abc的時候爲:

a符合a,之後發現是先行斷言,判斷該位置即b處,爲b,符合斷言,之後從該位置即a(因爲零寬度先行斷言的回溯使得位置指針不因斷言改變)繼續匹配,發現可以匹配b,因此匹配結果爲ab。


2,(?!X) 預測其前邊字串匹配位置後不是X。

(?!X)的工作過程與(?=X)相似,其是零寬度負向先行斷言


3,(?<=X) 預測其後字串匹配位置前的爲X。因此其前邊的字串必須是以X爲結尾的。

其是零寬度正向後行斷言

例如a(?=b)c無法匹配任何字符串,因爲其預測c之前是b,而又要求匹配a。

其工作過程爲:

左邊匹配後,字符串引擎匹配位置右移,然後發現表達式是lookbehind斷言,因此,斷言從左邊一定的位置與lookbehind表達式進行匹配以進行lookbehind斷言(注意字符串引擎匹配位置指針不會變動,依然是在斷言左邊的表達式匹配完後的位置上),如果斷言成功,則繼續匹配下一個。


例如:

b(?<=b)c 可以匹配“abc"。

a不是b,下一個b是b,發現是後行斷言,當前位置(在c處)後移一個,到b處,判斷該處是b,符合斷言,繼續從b後即c開始匹配,符合c,匹配結果爲bc。


4,(?<!X) 預測其後字串匹配位置前的不爲X。
其是零寬度負向後行斷言


5,(?:X) 預測其後是X,但是不進行字符位置回溯,因此會改變字符串引擎匹配位置指針。
也就是說,它不是零寬度的。
例如:

(?=b)b可以匹配“bc"中的b;但是(?:b)b則不能匹配"bc"中的b,因爲其預測爲b後,指針到達了c,c不是b,因此不符合;(?:b)c則可以匹配"bc"中的bc。


6,(?>X)預測其後是X,但是不進行字符位置回溯,因此會改變字符串引擎匹配位置指針。例如:

(?>b)b則不能匹配"bc"中的b;(?>b)c則可以匹配"bc"中的bc。


注意:Java後行斷言不支持其中使用*、+、?等元字符,但是支持{n,m},因爲前邊那些使得無法確定後行斷言後要回溯的位置多少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章