正則表達式:Pattern類與Matcher類詳解 – JAVA編程語言程序開發技術文章

一、捕獲組的概念
 捕獲組可以通過從左到右計算其開括號來編號,編號是從1 開始的。例如,在表達式((A)(B(C)))中,存在四個這樣的組:
 
1     ((A)(B(C)))
 2     (A)
 3     (B(C))
 4     (C)
 組零始終代表整個表達式。 以(?) 開頭的組是純的非捕獲 組,它不捕獲文本,也不針對組合計進行計數。
 
與組關聯的捕獲輸入始終是與組最近匹配的子序列。如果由於量化的緣故再次計算瞭組,則在第二次計算失敗時將保留其以前捕獲的值(如果有的話)例如,將字符串"aba" 與表達式(a(b)?)+ 相匹配,會將第二組設置為"b"。在每個匹配的開頭,所有捕獲的輸入都會被丟棄。
 
二、詳解Pattern類和Matcher類
 
java正則表達式通過java.util.regex包下的Pattern類與Matcher類實現(建議在閱讀本文時,打開java API文檔,當介紹到哪個方法時,查看java API中的方法說明,效果會更佳).
 Pattern類用於創建一個正則表達式,也可以說創建一個匹配模式,它的構造方法是私有的,不可以直接創建,但可以通過Pattern.complie(String regex)簡單工廠方法創建一個正則表達式,
 Java代碼示例:
 Pattern p=Pattern.compile("\\w+");
 p.pattern();//返回\w+
 
pattern() 返回正則表達式的字符串形式,其實就是返回Pattern.complile(String regex)的regex參數
 
1.Pattern.split(CharSequence input)
 Pattern有一個split(CharSequence input)方法,用於分隔字符串,並返回一個String[],我猜String.split(String regex)就是通過Pattern.split(CharSequence input)來實現的.
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 String[] str=p.split("我的QQ是:456456我的電話是:0532214我的郵箱是:aaa@aaa.com");
 
結果:str[0]="我的QQ是:" str[1]="我的電話是:" str[2]="我的郵箱是:aaa@aaa.com"
 
2.Pattern.matcher(String regex,CharSequence input)是一個靜態方法,用於快速匹配字符串,該方法適合用於隻匹配一次,且匹配全部字符串.
 Java代碼示例:
 Pattern.matches("\\d+","2223");//返回true
 Pattern.matches("\\d+","2223aa");//返回false,需要匹配到所有字符串才能返回true,這裡aa不能匹配到
 Pattern.matches("\\d+","22bb23");//返回false,需要匹配到所有字符串才能返回true,這裡bb不能匹配到
 
3.Pattern.matcher(CharSequence input)
 說瞭這麼多,終於輪到Matcher類登場瞭,Pattern.matcher(CharSequence input)返回一個Matcher對象.
 Matcher類的構造方法也是私有的,不能隨意創建,隻能通過Pattern.matcher(CharSequence input)方法得到該類的實例.
 Pattern類隻能做一些簡單的匹配操作,要想得到更強更便捷的正則匹配操作,那就需要將Pattern與Matcher一起合作.Matcher類提供瞭對正則表達式的分組支持,以及對正則表達式的多次匹配支持.
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 Matcher m=p.matcher("22bb23");
 m.pattern();//返回p 也就是返回該Matcher對象是由哪個Pattern對象的創建的
 
4.Matcher.matches()/ Matcher.lookingAt()/ Matcher.find()
 Matcher類提供三個匹配操作方法,三個方法均返回boolean類型,當匹配到時返回true,沒匹配到則返回false
 
matches()對整個字符串進行匹配,隻有整個字符串都匹配瞭才返回true
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 Matcher m=p.matcher("22bb23");
 m.matches();//返回false,因為bb不能被\d+匹配,導致整個字符串匹配未成功.
 Matcher m2=p.matcher("2223");
 m2.matches();//返回true,因為\d+匹配到瞭整個字符串
 
我們現在回頭看一下Pattern.matcher(String regex,CharSequence input),它與下面這段代碼等價
 Pattern.compile(regex).matcher(input).matches()
 
lookingAt()對前面的字符串進行匹配,隻有匹配到的字符串在最前面才返回true
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 Matcher m=p.matcher("22bb23");
 m.lookingAt();//返回true,因為\d+匹配到瞭前面的22
 Matcher m2=p.matcher("aa2223");
 m2.lookingAt();//返回false,因為\d+不能匹配前面的aa
 
find()對字符串進行匹配,匹配到的字符串可以在任何位置.
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 Matcher m=p.matcher("22bb23");
 m.find();//返回true
 Matcher m2=p.matcher("aa2223");
 m2.find();//返回true
 Matcher m3=p.matcher("aa2223bb");
 m3.find();//返回true
 Matcher m4=p.matcher("aabb");
 m4.find();//返回false
 
5.Mathcer.start()/ Matcher.end()/ Matcher.group()
 當使用matches(),lookingAt(),find()執行匹配操作後,就可以利用以上三個方法得到更詳細的信息.
 start()返回匹配到的子字符串在字符串中的索引位置.
 end()返回匹配到的子字符串的最後一個字符在字符串中的索引位置.
 group()返回匹配到的子字符串
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 Matcher m=p.matcher("aaa2223bb");
 m.find();//匹配2223
 m.start();//返回3
 m.end();//返回7,返回的是2223後的索引號
 m.group();//返回2223
 
Mathcer m2=m.matcher("2223bb");
 m.lookingAt();   //匹配2223
 m.start();   //返回0,由於lookingAt()隻能匹配前面的字符串,所以當使用lookingAt()匹配時,start()方法總是返回0
 m.end();   //返回4
 m.group();   //返回2223
 
Matcher m3=m.matcher("2223bb");
 m.matches();   //匹配整個字符串
 m.start();   //返回0,原因相信大傢也清楚瞭
 m.end();   //返回6,原因相信大傢也清楚瞭,因為matches()需要匹配所有字符串
 m.group();   //返回2223bb
 
說瞭這麼多,相信大傢都明白瞭以上幾個方法的使用,該說說正則表達式的分組在java中是怎麼使用的.
 start(),end(),group()均有一個重載方法它們是start(int i),end(int i),group(int i)專用於分組操作,Mathcer類還有一個groupCount()用於返回有多少組.
 Java代碼示例:
 Pattern p=Pattern.compile("([a-z]+)(\\d+)");
 Matcher m=p.matcher("aaa2223bb");
 m.find();   //匹配aaa2223
 m.groupCount();   //返回2,因為有2組
 m.start(1);   //返回0 返回第一組匹配到的子字符串在字符串中的索引號
 m.start(2);   //返回3
 m.end(1);   //返回3 返回第一組匹配到的子字符串的最後一個字符在字符串中的索引位置.
 m.end(2);   //返回7
 m.group(1);   //返回aaa,返回第一組匹配到的子字符串
 m.group(2);   //返回2223,返回第二組匹配到的子字符串
 
現在我們使用一下稍微高級點的正則匹配操作,例如有一段文本,裡面有很多數字,而且這些數字是分開的,我們現在要將文本中所有數字都取出來,利用java的正則操作是那麼的簡單.
 Java代碼示例:
 Pattern p=Pattern.compile("\\d+");
 Matcher m=p.matcher("我的QQ是:456456 我的電話是:0532214 我的郵箱是:aaa123@aaa.com");
 while(m.find()) {
      System.out.println(m.group());
 }
 
輸出:
 456456
 0532214
 123
 
如將以上while()循環替換成
 while(m.find()) {
      System.out.println(m.group());
      System.out.print("start:"+m.start());
      System.out.println(" end:"+m.end());
 }
 則輸出:
 456456
 start:6 end:12
 0532214
 start:19 end:26
 123
 start:36 end:39
 
現在大傢應該知道,每次執行匹配操作後start(),end(),group()三個方法的值都會改變,改變成匹配到的子字符串的信息,以及它們的重載方法,也會改變成相應的信息.
 註意:隻有當匹配操作成功,才可以使用start(),end(),group()三個方法,否則會拋出java.lang.IllegalStateException,也就是當matches(),lookingAt(),find()其中任意一個方法返回true時,才可以使用.
摘自kofandlizi的專欄
 

 

發佈留言