java中的正则表达式捕获组与引用的概念
今天群里有個人問,怎樣用增則表達式匹配三角形的三邊,其實只是要匹配三個數(shù)字而已,如 301 402 503 開始認為很簡單,我就寫了一個 ??"(([1-9]\\d?)\\s){2}$2" 結(jié)果他說錯了,我感覺很奇怪,于是自己打開電腦試了試,果然是錯的,然后看了看以前的筆記,發(fā)現(xiàn)我的Back 引用捕獲組錯了,因為$符號是在不同字符串中對捕獲組的引用看下面這個方法
public static void text_1(){String str="我。。我要。。。要要要。。學(xué)。。學(xué)。編。。。程";str=str.replaceAll("\\。+","");System.out.println(str);<span style="background-color: rgb(255, 255, 153);">str=str.replaceAll("(.)\\1*","$1");</span>System.out.println(str);}這句話的意思是將$1調(diào)用(.)匹配到的結(jié)果,注意是匹配到的結(jié)果,也就是()括號里匹配到什么就被調(diào)用什么,這也是本人為什么要寫這篇博客的原因所在。? 可能大家還沒有理解我的意思,下面跟著我來理解
? 上面說的$是在不同字符串中的引用捕獲組,我一直強調(diào)的是引用的是結(jié)果,看下面這個代碼:
public void test(){<span style="color:#3333ff;">String regex="(([1-9]\\d?)\\s){2}\2";</span>String str="3 4 5";System.out.println(str.matches(regex));}上面這段代碼是我一直想不懂最后的結(jié)果為什么是false, String regex="(([1-9]\\d?)\\s){2}\2"; ? ? ? ??
我們來分析這句話:([1-9]\\d?) ?這句的意思是匹配一個正整數(shù),如3,401,等 ? 。([1-9]\\d?)\\s這句話是匹配一個數(shù)之后空格隔開,(([1-9]\\d?)\\s){2}正好出現(xiàn)兩次也就是如:3 4 ,最后\2是調(diào)用角標為2的捕獲組,也就是([1-9]\\d?) ,自己一直在思考為什么是錯的,知道看到一篇博文才恍然大悟,引用捕獲組的不是捕獲組里面的表達式,而是引用捕獲組所捕獲到的具體內(nèi)容,拿上面的例子來說:當?shù)谝淮纹ヅ鋾r,([1-9]\\d?) 此匹配組所捕獲的是3這個具體的字符串,所以你下次引用時就必須為3這個字符串,而不是再次調(diào)用([1-9]\\d?) 這個正則表達式這么簡單,這就是我以前最大的誤區(qū),所以,自己也是花了很多時間才發(fā)現(xiàn),改正上面的代碼:
public static void test(){<span style="color:#000099;">String regex="([1-9]\\d*\\s){2}[1-9]\\d*";</span>String str="304 4 5";System.out.println(str.matches(regex));}歸根結(jié)底是我將{n}出現(xiàn)次數(shù)和\n引用捕獲組搞混淆了,希望大家不要記錯了!!!下面是我為大家扒過來的我覺得比較好的博文,這里我只是強調(diào)捕獲組引用的概念,其他關(guān)于正則表達式不做過多的介紹,(現(xiàn)在已經(jīng)深夜1.30了,哎,苦逼的程序員人生啊,該睡了)看下面代碼:
Regex :
- 本文主要講述正則表達式中的捕獲組(Capturing Group)的概念
- 本文的正則表達式在 Java 中測試(需要注意的是這里的部分正則表達式在?Java7?中才能應(yīng)用,下面會注明)
- 本文正則表達式用???????????高亮標出
Capturing Group : (X)
簡單的理解就是把正則表達式中的某部分用 () 括起來表示為一個組,純理論解釋不怎么好解釋,詳細還看下面的舉例。
??????? 舉例:
- (Ggi)cci?與Ggicci?都匹配 "Ggicci",只不過前面把 Ggi 作為一個捕獲組,在匹配到的同時它可以捕獲 "Ggi" 這樣的字符串供逆向引用(Back Reference),見下一欄。
- Ggicci*?與(Ggicci)*?不同在于Ggicci*?匹配的是 "Ggicci" 和 "Ggicci…i" 這種情況,而(Ggicci)*?匹配的是 "Ggicci" 和 "GgicciGgicci…Ggicci" 這種情況。
Back Reference :
逆向引用指的是正則表達式中某個捕獲組捕獲到的字符串供正則表達式構(gòu)建其自身匹配規(guī)則的方式。這是我自己歸納的理論,聽起來肯定很晦澀,詳細見下面講解
????????捕獲組的編號與命名:
??????? 如?((A)(B(C)))?“摘自Java7 Doc”,這里有 4 個組:
編號 捕獲組 1 ((A)(B(C))) 2 (A) 3 (B(C)) 4 (C)
??????? 在未對捕獲組人為命名的時候,對捕獲組的編號是默認的從左到右依次萃取 (?和與之對應(yīng)成一對的 )。如上,一共 4 個 ( ,所以有 4 個組,按 ( 的出現(xiàn)次序編號。
- (?<name>X)?命名捕獲組為 name,在?Java7?中; 1: String source = "Ggicci was born in 1991 and is 20 years old now. He weights 54kg and is 170cm tall."; 2: Pattern pattern = Pattern.compile("(?<user>[Gg]gicci)|(?<digital>\\d+)"); 3: Matcher matcher = pattern.matcher(source); 4: while (matcher.find()) { 5: System.out.println(matcher.group()); 6: } 代碼中的正則表達式(已加粗)匹配 Ggicci 或 ggicci 或一段數(shù)字,輸出為: 1: //輸出: 2: Ggicci 3: 1991 4: 20 5: 54 6: 170 (?<user>[Gg]gicci)?把捕獲組命名為 user,我們用 Matcher 類的 group(String name) 方法,即 matcher.group("user"); 可以獲取該捕獲組捕獲的內(nèi)容,其它的捕獲組內(nèi)容將為 null: 1: System.out.println(matcher.group("user")); //替換上面 while 循環(huán)中的輸出語句 2: //輸出: 3: Ggicci 4: null 5: null 6: null 7: null 當然用 Matcher 類的 group(int group) 方法也可以,這里 user 捕獲組的默認編號為 1,所以 matcher.group(1) 同 matcher.group("user") 一樣。(?<digital>\d+)?也同樣去理解。
- (?:X)?取消捕獲組命名,注意這種方式連捕獲組默認的編號也會取消,所以在調(diào)用 Matcher.group(int) 或 Matcher.group(String) 的時候會異常;
- \n?表示引用第 n 個捕獲組捕獲到的內(nèi)容; 1: String source = "Hello, my my name is uh.. is is Gg.. ggicci ggicci ggicci ggicci"; 2: Pattern pattern = Pattern.compile("\\b(\\w+)\\b((\\s+)\\1\\b)+"); 3: Matcher matcher = pattern.matcher(source); 4: while (matcher.find()) { 5: System.out.println(matcher.group()); 6: } 這段正則表達式?\b(\w)\b((\s+)\1)+?匹配字符串重復(fù)的以空格符間隔的單詞。其中?\1?引用了捕獲組?(\w)?匹配到的內(nèi)容。比如 (\w) 第一次匹配了 "Hello",\1 引用了 "Hello" 后正則表達式其實已經(jīng)變成了\bHello\b((\s+)Hello)+?了(這是從形式上去理解,具體內(nèi)部機制如何,親,我目前真的不知道 : )),但是顯然后面沒有 "Hello" 可以匹配了,(\w) 第二次匹配了 "my",\1 引用了 "my",找到匹配,然后依次下去,輸出如下: 1: //輸出: 2: my my 3: is is 4: ggicci ggicci ggicci ggicci
- \k<name>?表示引用命名為 name 的捕獲組捕獲到的內(nèi)容,在Java7?中; 1: //這里同上面的正則表達式一樣,只不過給 \1 取了個名字叫 repeat 2: //然后用 \k<repeat> 代替 \1 而已 3: Pattern pattern = Pattern.compile("\\b(?<repeat>\\w+)\\b((\\s+)\\k<repeat>\\b)+");
-
總結(jié)
以上是生活随笔為你收集整理的java中的正则表达式捕获组与引用的概念的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中的enum枚举类
- 下一篇: AutoCloseable的用法