正則表達式在字符串處理中常常使用,關於正則簡單的用法相信有一點程序基礎的人都懂得一些,這裏就不介紹簡單基礎了。這裏主要講解一下在JAVA中實現了的正則的高級用法-分組與捕獲。
對於要重複單個字符,很是簡單,直接在字符後賣弄加上限定符便可,例如 a+ 表示匹配1個或一個以上的a,a?表示匹配0個或1個a。這些限定符以下所示:
html
X ? X ,一次或一次也沒有 X * X ,零次或屢次 X + X ,一次或屢次 X { n } X ,剛好 n 次 X { n ,} X ,至少 n 次 X { n , m } X ,至少 n 次,可是不超過 m 次
可是咱們若是要對多個字符進行重複怎麼辦呢?此時咱們就要用到分組,咱們可使用小括號"()"來指定要重複的子表達式,而後對這個子表達式進行重複,例如:(abc)? 表示0個或1個abc 這裏一 個括號的表達式就表示一個分組 。
分組能夠分爲兩種形式,捕獲組和非捕獲組。
java
捕獲組
捕獲組能夠經過從左到右計算其開括號來編號 。例如,在表達式 ((A)(B(C))) 中,存在四個這樣的組:
正則表達式
1 ((A)(B(C))) 2 /A 3 (B(C)) 4 (C)
組零始終表明整個表達式之因此這樣命名捕獲組是由於在匹配中,保存了與這些組匹配的輸入序列的每一個子序列。捕獲的子序列稍後能夠經過 Back 引用 在表達式中使用,也能夠在匹配操做完成後從匹配器檢索。
Back 引用 是說在後面的表達式中咱們可使用組的編號來引用前面的表達式所捕獲到的文本序列(是文本不是正則) 。
例如 ([" ']).* /1 其中使用了分組,/1就是對引號這個分組的引用,它匹配包含在兩個引號或者兩個單引號中的全部字符串,如,"abc" 或 " ' " 或 ' " ' ,可是請注意,它並不會對" a'或者 'a"匹配。緣由上面已經說明,Back引用只是引用文本而不是表達式。
非捕獲組
以 (?) 開頭的組是純的非捕獲 組,它不捕獲文本 ,也不針對組合計進行計數。就是說,若是小括號中以?號開頭,那麼這個分組就不會捕獲文本,固然也不會有組的編號,所以也不存在Back 引用。
在Java中,支持的非捕獲組,有以下幾種:
測試
(?= X ) X ,經過零寬度的正 lookahead (?! X ) X ,經過零寬度的負 lookahead (?<= X ) X ,經過零寬度的正 lookbehind (?<! X ) X ,經過零寬度的負 lookbehind
這四個非捕獲組用於匹配表達式X,可是不包含表達式的文本。
(?=X ) 零寬度正先行斷言。僅當子表達式 X 在 此位置的右側匹配時才繼續匹配。例如,/w+(?=/d) 與後跟數字的單詞匹配,而不與該數字匹配。此構造不會回溯。
(?!X) 零寬度負先行斷言。僅當子表達式 X 不在 此位置的右側匹配時才繼續匹配。例如,例如,/w+(?!/d) 與後不跟數字的單詞匹配,而不與該數字匹配 。
(?<=X) 零寬度正後發斷言。僅當子表達式 X 在 此位置的左側匹配時才繼續匹配。例如,(?<=19)99 與跟在 19 後面的 99 的實例匹配。此構造不會回溯。
(?<!X) 零寬度負後發斷言。僅當子表達式 X 不在此位置的左側匹配時才繼續匹配。例如,(?<!19)99 與不跟在 19 後面的 99 的實例匹配
舉例:
上面都是理論性的介紹,這裏就使用一些例子來講明一下問題:
一、測試匹配性 (?<!4)56(?=9) 這裏的含義就是匹配後面的文本56前面不能是4,後面必須是9組成。所以,能夠匹配以下文本 5569 ,與4569不匹配。
2 、提取字符串 提取 da12bka3434bdca4343bdca234bm 提取包含在字符a和b之間的數字,可是這個a以前的字符不能是c,b後面的字符必須是d才能提取。
例如這裏就只有3434這個數字知足要求。那麼咱們怎麼提取呢?
首先咱們寫出提取這個字符串的表達式: (?<!c)a(/d+)bd 這裏就只有一個捕獲組(/d+)
JAVA代碼片斷以下:
spa
Pattern p = Pattern.compile( "(?<!c)a(//d+)bd " ); Matcher m = p.matcher( "da12bka3434bdca4343bdca234bm" ); while (m.find()){ System.out.println(m.group( 1 )); //咱們只要捕獲組1的數字便可。結果 3434 System.out.println(m.group(0)); // 0組是整個表達式,看這裏,並無提煉出(?<!c)的字符 。結果 a3434bd }
能夠看到,非捕獲組,最後是不會返回結果的,由於它自己並不捕獲文本。
code