Java中使用Regex

來源:互聯網
上載者:User
最近要在項目中做HTML解析,本想使用NekoHTML來解析,但看了下NekoHTML有點複雜,故採用了一種便捷,笨的方式來完成項目的要求. Regex此時發揮了她巨大的威力,為我排憂解難,很快便完成了HTML解析工作. 在解析期間,研究了很多javaRegex使用方法,頗得一些經驗,不敢獨享,願與大家共用. javaRegex通過 java.util.regex包下的Pattern類與Matcher類實現( 建議在閱讀本文時,開啟java API文檔,當介紹到哪個方法時,查看java API中的方法說明,效果會更佳). Pattern類用於建立一個Regex,也可以說建立一個匹配模式,它的構造方法是私人的,不可以直接建立,但可以通過Pattern.complie(String regex)簡單Factory 方法建立一個Regex, Java程式碼範例: Pattern p=Pattern.compile("//w+"); p.pattern();//返回 /w+ pattern() 返回Regex的字串形式,其實就是返回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類提供了對Regex的分組支援,以及對Regex的多次匹配支援. 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 說了這麼多,相信大家都明白了以上幾個方法的使用,該說說Regex的分組在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時,才可以使用. 6.Matcher. replaceAll(String replacement) / Matcher.replaceFirst(String replacement) 大家應該知道String.replaceAll()和String.replaceFirst()兩個方法的功能,其實它與Matcher.replaceAll()和Matcher.replaceFirst()的功能是一樣的,只不過是使用方式不一樣.例如我要將某文本中的所有數字變成*使用String完成該要求Java程式碼範例: String str="我的QQ是:456456 我的電話是:0532214 我的郵箱是:aaa123@aaa.com";System.out.println(str.replaceAll("//d","*")); 輸出: 我的QQ是:****** 我的電話是:******* 我的郵箱是:aaa***@aaa.com 現在我們用Matcher完成該要求Java程式碼範例:Pattern p=Pattern.compile("//d");Matcher m=p.matcher("我的QQ是:456456 我的電話是:0532214 我的郵箱是:aaa123@aaa.com");System.out.println(m.replaceAll("*")); 輸出: 我的QQ是:****** 我的電話是:******* 我的郵箱是:aaa***@aaa.com String.replaceAll()應該是調用了Matcher.replaceAll(),String.replaceAll()與下面這段代碼等價 Pattern. compile( regex). matcher( str). replaceAll(replacement) 至於Matcher.replaceFirst()也很簡單,它與String.replaceFirst()功能一樣,我就不多說了. str.replaceFirst( regex, replacement)與下面這段代碼等價 Pattern. compile( regex). matcher( str). replaceFirst( replacement7.Matcher. appendReplacement(StringBuffer sb, String replacement) / Matcher.appendTail(StringBuffer sb) 將當前匹配子串替換為指定字串,並且將替換後的子串以及其之前到上次匹配子串之後的字串段添加到一個StringBuffer對象裡,而appendTail(StringBuffer sb) 方法則將最後一次匹配工作後剩餘的字串添加到一個StringBuffer對象裡.看例子:Java程式碼範例:Pattern p=Pattern.compile("//d+");Matcher m=p.matcher("我的QQ是:456456 我的電話是:0532214 我的郵箱是:aaa123@aaa.com");StringBuffer sb=new StringBuffer();m.find();  //匹配到456456m.appendReplacement(sb,"*");  //將456456之前的字串追加到sb,再將456456替換為*,並追加到sbSystem.out.println(sb.toString());m.appendTail(sb);  //將前面替換過的內容串連後面未替換過的內容,並放入sbSystem.out.println(sb.toString()); 輸出:我的QQ是:*
我的QQ是:* 我的電話是:0532214 我的郵箱是:aaa123@aaa.com 再看一個例子Java程式碼範例:Pattern p=Pattern.compile("//d+");Matcher m=p.matcher("我的QQ是:456456 我的電話是:0532214 我的郵箱是:aaa123@aaa.com");StringBuffer sb=new StringBuffer();while(m.find()) {    m.appendReplacement(sb,"*");    System.out.println(sb.toString());}m.appendTail(sb);System.out.println("使用appendTail()的最終內容是:"+sb.toString()); 輸出:我的QQ是:*
我的QQ是:* 我的電話是:*
我的QQ是:* 我的電話是:* 我的郵箱是:aaa*
使用appendTail()的最終內容是:我的QQ是:* 我的電話是:* 我的郵箱是:aaa*@aaa.com 關於這兩個方法就介紹到這,如果不明白的話,還需要自己動下手,認真體會一下其內涵.  8.Matcher.region(int start, int end) / Matcher.regionEnd() / Matcher.regionStart()

我們在做匹配操作時,預設去匹配的是整個字串,例如有一字串"aabbcc",使用"//d+"去find()時,是從第一個a開始匹配,也就是索引號為0的位置,開始去匹配,當索引號為0的位置沒有匹配到時,就去下一個位置去匹配...直到匹配到子字串或匹配完最後一個字元索引號才結束,很顯然"//d+"不能匹配"aabbcc",當它匹配完最後一個c時,結束本次匹配,宣告匹配失敗,也就是說它會去匹配完整個字串,能不能不去匹配完整個字串呢,答案是可以的.region(int start,int end)就是用來設定此匹配器的地區限制。先來看一個例子.Java程式碼範例:Pattern p=Pattern.compile("//d+");String content="aaabb2233cc";
Matcher m=p.matcher(content);
System.out.println(m); 輸出: java.util.regex.Matcher[pattern=/d+ region=0,11 lastmatch=] 可以看到region=0,11 表示start=0,end=11,更通俗的說就是當去匹配字串,先從索引號為0的位置去匹配,如果匹配到了子字串就返回,如果沒有匹配到則到下一個位置去匹配,一直匹配到索引號為11-1的字元就結束匹配.為什麼是11呢,因為content.length()==11現在你應該明白了它的作用,來看一個例子.Java程式碼範例:Pattern p=Pattern.compile("//d+");String content="aaabb2233cc";
Matcher m=p.matcher(content);
m.find();  //匹配到2223,返回true Matcher m2=p.matcher(content);m2.region(0,5);m2.find();  //返回false,只去匹配索引號0至5-1的字元,沒有匹配到 Matcher m3=p.matcher(content);m2.region(3,8);m2.find();  //返回truem2.group();  //返回223,為什麼,請數一下索引號就知道了. Matcher.regionStart()返回region(int start,int end)中的start值,預設為0Matcher.regionEnd()返回region(int start,int end)中的end值,預設為去匹配字串的length()值
9.Matcher. reset() / Matcher.reset(CharSequence input) 用於重設匹配器。看樣本Java程式碼範例:Pattern p=Pattern.compile("[a-z]+");String content="aaabb2233cc";
Matcher m=p.matcher(content);  //此時m剛建立出來,為最初狀態m.find();m.group();  //返回aaabbm.find();m.group();  //返回cc Matcher m2=p.matcher(content);  //此時m2剛建立出來,為最初狀態m.find();m.group();  //返回aaabbm.reset();  //恢複到了最初狀態,此時相當於m2剛建立出來m.find();m.group();  //返回aaabb,相信大家應該知道了吧  Matcher.reset(CharSequence input) 恢複到最初狀態,並將匹配字串換成input,以後執行匹配操作時,就來匹配input,而不匹配原來的字串了.  10.Matcher.toMatchResult() 大家查看一下java API 對Matcher類的說明,會發現它實現了MatchResult 介面,這個介面只有以下幾個方法groupCount() group() / group(int i)start() / start(int i) end() / end(int i) 至於這幾個方法的功能前面已經介紹過,現在我們來看一下toMatchResult() 是如何使用的Java程式碼範例:Pattern p=Pattern.compile("//d+");
Matcher m=p.matcher("我的QQ是:456456 我的電話是:0532214 我的郵箱是:aaa123@aaa.com");
List list=new ArrayList();
while(m.find()) {
    list.add(m.toMatchResult());
}
MatchResult matchResult=null;
Iterator it=list.iterator();
int i=1;
while(it.hasNext()) {
    matchResult=(MatchResult)it.next();
    System.out.print("第"+(i++)+"次匹配到的資訊: ");
    System.out.println(matchResult.group()+"/t/t"+matchResult.start()+"/t"+matchResult.end());
} 輸出:第1次匹配到的資訊: 456456           6        12
第2次匹配到的資訊: 0532214        19      26
第3次匹配到的資訊: 123                 36      39 現在你應該知道,toMatchResult()用於儲存某次匹配後的資訊,待以後再使用.方法使用就說到這裡,現在再介紹一個執行個體有這樣一個需求,有一個HTML檔案,需要將其中的內容抽取出來,並不帶HTML標籤,如果使用Regex,這是一件很容易的事情. 前提是這個HTML檔案只保留了<body></body>標籤以內的內容.Java程式碼範例: String html="<div><font  color='red'>example1</font></div>"; //可以是任何html檔案原始碼,但格式一定要正確 Pattern p=Pattern.compile("<[^>]*>"); Matcher m=p.matcher(html); String result=m.replaceAll(""); System.out.println(result); 輸出:example1 

參考資料:
java.util.regex的API文檔
陳廣佳的JAVARegex--Pattern和Matcher

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.