posts - 0,  comments - 5,  trackbacks - 0
          最近要在項目中做HTML解析,本想使用NekoHTML來解析,但看了下NekoHTML有點復雜,故采用了一種便捷,笨的方式來完成項目的要求. 正則表達式此時發揮了她巨大的威力,為我排憂解難,很快便完成了HTML解析工作.
          在解析期間,研究了很多java正則表達式使用方法,頗得一些經驗,不敢獨享,愿與大家共享.
          -
          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時,才可以使用.
          -
          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(replacement)
          ?
          7.Matcher. appendReplacement ( StringBuffer sb, String replacement) / Matcher.appendTail(StringBuffer sb)
          -將當前匹配子串替換為指定字符串,并且將替換后的子串以及其之前到上次匹配子串之后的字符串段添加到一個StringBuffer對象里,而appendTai-l(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();? //匹配到456456
          m.appendReplacement(sb,"*");? //將456456之前的字符串追加到sb,再將456456替換為*,并追加到sb
          System.out.println(sb.toString());
          m.appendTail(sb);? //將前面替換過的內容連接后面未替換過的內容,并放入sb
          System.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();? //返回true
          m2.group();? //返回223,為什么,請數一下索引號就知道了.
          ?
          Matcher.regionStart()返回region(int start,int end)中的start值,默認為0
          Matcher.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();? //返回aaabb
          m.find();
          m.group();? //返回cc
          ?
          Matcher m2=p.matcher(content);? //此時m2剛創建出來,為最初狀態
          m.find();
          m.group();? //返回aaabb
          m.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標簽,如果使用正則表達式,這是一件很容易的事情. 前提是這個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文檔
          陳廣佳的JAVA正則表達式--Pattern和Matcher

          posted on 2007-12-15 12:19 crazy 閱讀(577) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 肃北| 虎林市| 托里县| 浪卡子县| 石城县| 郯城县| 呈贡县| 睢宁县| 谷城县| 凤庆县| 方山县| 云和县| 甘德县| 绵竹市| 亚东县| 西贡区| 清水河县| 万载县| 江都市| 土默特左旗| 阳新县| 韶关市| 襄樊市| 垣曲县| 台中县| 永平县| 大竹县| 南汇区| 共和县| 宁陵县| 黔东| 屏山县| 呼伦贝尔市| 竹北市| 金山区| 临高县| 康保县| 禹城市| 城市| 杭州市| 玉环县|