JAVA 正則表達式 非捕獲組(特殊構造) – JAVA編程語言程序開發技術文章

 在 java api 文檔中的正則表達式關於特殊構造(非捕獲組)的說明看不懂。例如:

(?:X)         X,作為非捕獲組
(?idmsux-idmsux) Nothing,但是將匹配標志由 on 轉為 off
(?idmsux-idmsux:X) X,作為帶有給定標志 on – off 的非捕獲組
(?=X) X,通過零寬度的正 lookahead
(?!X)  X,通過零寬度的負 lookahead
(?<=X) X,通過零寬度的正 lookbehind
(?<!X) X,通過零寬度的負 lookbehind
(?>X) X,作為獨立的非捕獲組
 

    這些字都說的很抽象。不懂……。還是搜索下去。找到 火龍果 的解釋如下:以 (? 開頭,) 結尾的都稱為非捕獲組,在匹配完成後在內存中不保留匹配到的字符。非捕獲組的應用比較復雜,這裡隻能簡單地說一下它們的意思。

1、(?:X) X,作為非捕獲組

與捕獲組 ( ) 的意思一樣也是將其作為一組進行處理,與捕獲組的區別在於不捕獲匹配的文本,僅僅作為分組。

比如:要匹配 123123 這個,就可以寫為 (123)\1 使用反向引用,這時隻能用捕獲組,在匹配 123 後會保留在內存中,便於反向引用,而 (?:123) 在匹配完後則不會保留,區別僅在於此。

2、(?idmsux-idmsux)  Nothing,但是將匹配標志i d m s u x on – off

用於標志匹配,比如:表達式 (?i)abc(?-i)def 這時,(?i) 打開不區分大小寫開關,abc 匹配不區分大小地進行匹配,(?-i) 關閉標志,恢復不區分大小寫,這時的 def 隻能匹配 def

3、(?idmsux-idmsux:X)  X,作為帶有給定標志 i d m s u x on – off

與上面的類似,上面的表達式,可以改寫成為:(?i:abc)def,或者 (?i)abc(?-i:def)

4、(?=X) X,通過零寬度的正 lookahead

5、(?!X) X,通過零寬度的負 lookahead

(?=X) 表示當前位置(即字符的縫隙)後面允許出現的字符,比如:表示式 a(?=b),在字符串為 ab 時,可能匹配 a,後面的 (?=b) 表示,a 後面的縫隙,可以看作是零寬度。 (?!X) 表示當前位置後面不允許出現的字符

 6、(? <=X) X,通過零寬度的正 lookbehind

7、(? <!X) X,通過零寬度的負 lookbehind

這兩個與上面兩個類似,上面兩個是向後看,這個是向前看

 8、(?>X) X,作為獨立的非捕獲組

匹配成功不進行回溯,這個比較復雜,也侵占量詞“+”可以通用,比如:\d++ 可以寫為 (?>\d+)。

 我認為,第1、2、3點比較好理解,4、5、6、7看類懂,還是用示例來說明:從“aacabab”找a,且後面隻允許出現b。代碼如下:

 Pattern p = Pattern.compile("a(?=b)"); 
Matcher m = p.matcher("aacabab"); 
while(m.find()) { 
System.out.println(m.group()+", start="+m.start()+", end="+m.end()); 

運行結果:
 a, start=3, end=4 
a, start=5, end=6 
個人理解:在(?=b)這個“式”後面允許出現b,且這個“式”不占正則表達式位置(所謂0寬度),lookahead 的意思是b字符的前面,它前面緊接著是a,也就是a後面出現b。

8比較難理解,這個根據 火龍果 推薦的鏈接找到答案 http://www.regular-expressions.info/atomic.html

其中說的示例:來看 /\b(integer|insert|in)\b/ 匹配 integers 過程,第一個,當integer\b匹配到s時失敗,然後字符串(integers)會回溯到i,再接著第二個(insert)去匹配。而把模式寫成 /\b(?>integer|insert|in)\b/ 在剛才的第一個匹配失敗,字符串(integers)不會回溯瞭,也不會有第二個去匹配瞭,所有速度會快一點點。

但是寫 (?>X) 這種式子時要註意,是從左到右看的。/\b(?>integer|insert|in)\b/ ,與 /\b(?>in|integer|insert)\b/ 去匹配 insert,結果會不一樣,前者可以匹配到,後者不能,什麼原因自己分析下。一但匹配失敗就會跳過,所以應該長的寫在表達式前面. 

摘自  蔡園

發佈留言