1.21 Pattern类和Matcher类的使用
java.util.regex 是一個(gè)用正則表達(dá)式所訂制的模式來(lái)對(duì)字符串進(jìn)行匹配工作的類(lèi)庫(kù)包。它包括兩個(gè)類(lèi):Pattern 和 Matcher。
Pattern 對(duì)象是正則表達(dá)式編譯后在內(nèi)存中的表示形式,因此,正則表達(dá)式字符串必須先被編譯為 Pattern 對(duì)象,然后再利用該 Pattern 對(duì)象創(chuàng)建對(duì)應(yīng)的 Matcher 對(duì)象。執(zhí)行匹配所涉及的狀態(tài)保留在 Matcher 對(duì)象中,多個(gè) Matcher 對(duì)象可共享同一個(gè) Pattern 對(duì)象。
因此,典型的調(diào)用順序如下:
// 將一個(gè)字符串編譯成 Pattern 對(duì)象 Pattern p = Pattern.compile("a*b"); // 使用 Pattern 對(duì)象創(chuàng)建 Matcher 對(duì)象 Matcher m = p.matcher("aaaaab"); boolean b = m.matches(); // 返回 true上面定義的 Pattern 對(duì)象可以多次重復(fù)使用。如果某個(gè)正則表達(dá)式僅需一次使用,則可直接使用 Pattern 類(lèi)的靜態(tài) matches() 方法,此方法自動(dòng)把指定字符串編譯成匿名的 Pattern 對(duì)象,并執(zhí)行匹配,如下所示。
boolean b = Pattern.matches ("a*b","aaaaab"); // 返回 true上面語(yǔ)句等效于前面的三條語(yǔ)句。但采用這種語(yǔ)句每次都需要重新編譯新的 Pattern 對(duì)象,不能重復(fù)利用已編譯的 Pattern 對(duì)象,所以效率不高。Pattern 是不可變類(lèi),可供多個(gè)并發(fā)線程安全使用。
Matcher 類(lèi)提供了幾個(gè)常用方法,如表 1 所示。
表 1 Matcher 類(lèi)的幾個(gè)常用方法
| find() | 返回目標(biāo)字符串中是否包含與 Pattern 匹配的子串 | 
| group() | 返回上一次與 Pattern 匹配的子串 | 
| start() | 返回上一次與 Pattern 匹配的子串在目標(biāo)字符串中的開(kāi)始位置 | 
| end() | 返回上一次與 Pattern 匹配的子串在目標(biāo)字符串中的結(jié)束位置加 1 | 
| lookingAt() | 返回目標(biāo)字符串前面部分與 Pattern 是否匹配 | 
| matches() | 返回整個(gè)目標(biāo)字符串與 Pattern 是否匹配 | 
| reset() | 將現(xiàn)有的 Matcher 對(duì)象應(yīng)用于一個(gè)新的字符序列。 | 
在 Pattern、Matcher 類(lèi)的介紹中經(jīng)常會(huì)看到一個(gè) CharSequence 接口,該接口代表一個(gè)字符序列,其中 CharBuffer、String、StringBuffer、StringBuilder 都是它的實(shí)現(xiàn)類(lèi)。簡(jiǎn)單地說(shuō),CharSequence 代表一個(gè)各種表示形式的字符串。
通過(guò) Matcher 類(lèi)的 find() 和 group() 方法可以從目標(biāo)字符串中依次取出特定子串(匹配正則表達(dá)式的子串),例如互聯(lián)網(wǎng)的網(wǎng)絡(luò)爬蟲(chóng),它們可以自動(dòng)從網(wǎng)頁(yè)中識(shí)別出所有的電話號(hào)碼。下面程序示范了如何從大段的字符串中找出電話號(hào)碼。
public class FindGroup {public static void main(String[] args) {// 使用字符串模擬從網(wǎng)絡(luò)上得到的網(wǎng)頁(yè)源碼String str = "我想找一套適合自己的JAVA教程,盡快聯(lián)系我13500006666" + "交朋友,電話號(hào)碼是13611125565" + "出售二手電腦,聯(lián)系方式15899903312";// 創(chuàng)建一個(gè)Pattern對(duì)象,并用它建立一個(gè)Matcher對(duì)象// 該正則表達(dá)式只抓取13X和15X段的手機(jī)號(hào)// 實(shí)際要抓取哪些電話號(hào)碼,只要修改正則表達(dá)式即可Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}").matcher(str);// 將所有符合正則表達(dá)式的子串(電話號(hào)碼)全部輸出while (m.find()) {System.out.println(m.group());}} }運(yùn)行上面程序,看到如下運(yùn)行結(jié)果:
13500006666 13611125565 15899903312從上面運(yùn)行結(jié)果可以看出,find() 方法依次查找字符串中與 Pattern 匹配的子串,一旦找到對(duì)應(yīng)的子串,下次調(diào)用 find() 方法時(shí)將接著向下查找。
提示:通過(guò)程序運(yùn)行結(jié)果可以看出,使用正則表達(dá)式可以提取網(wǎng)頁(yè)上的電話號(hào)碼,也可以提取郵件地址等信息。如果程序再進(jìn)一步,可以從網(wǎng)頁(yè)上提取超鏈接信息,再根據(jù)超鏈接打開(kāi)其他網(wǎng)頁(yè),然后在其他網(wǎng)頁(yè)上重復(fù)這個(gè)過(guò)程就可以實(shí)現(xiàn)簡(jiǎn)單的網(wǎng)絡(luò)爬蟲(chóng)了。
find() 方法還可以傳入一個(gè) int 類(lèi)型的參數(shù),帶 int 參數(shù)的 find() 方法將從該 int 索引處向下搜索。start() 和 end() 方法主要用于確定子串在目標(biāo)字符串中的位置,如下程序所示。
public class StartEnd {public static void main(String[] args) {// 創(chuàng)建一個(gè)Pattern對(duì)象,并用它建立一個(gè)Matcher對(duì)象String regStr = "Java is very easy!";System.out.println("目標(biāo)字符串是:" + regStr);Matcher m = Pattern.compile("\\w+").matcher(regStr);while (m.find()) {System.out.println(m.group() + "子串的起始位置:" + m.start() + ",其結(jié)束位置:" + m.end());}} }上面程序使用 find()、group() 方法逐項(xiàng)取出目標(biāo)字符串中與指定正則表達(dá)式匹配的子串,并使用 start()、end() 方法返回子串在目標(biāo)字符串中的位置。運(yùn)行上面程序,看到如下運(yùn)行結(jié)果:
目標(biāo)字符串是:Java is very easy! Java子串的起始位置:0,其結(jié)束位置:4 is子串的起始位置:5,其結(jié)束位置:7 very子串的起始位置:8,其結(jié)束位置:12 easy子串的起始位置:13,其結(jié)束位置:17matches() 和 lookingAt() 方法有點(diǎn)相似,只是 matches() 方法要求整個(gè)字符串和 Pattern 完全匹配時(shí)才返回 true,而 lookingAt() 只要字符串以 Pattern 開(kāi)頭就會(huì)返回 true。reset() 方法可將現(xiàn)有的 Matcher 對(duì)象應(yīng)用于新的字符序列。看如下例子程序。
public class MatchesTest {public static void main(String[] args) {String[] mails = { "kongyeeku@163.com", "kongyeeku@gmail.com", "ligang@crazyit.org", "wawa@abc.xx" };String mailRegEx = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";Pattern mailPattern = Pattern.compile(mailRegEx);Matcher matcher = null;for (String mail : mails) {if (matcher == null) {matcher = mailPattern.matcher(mail);} else {matcher.reset(mail);}String result = mail + (matcher.matches() ? "是" : "不是") + "一個(gè)有效的郵件地址!";System.out.println(result);}} }上面程序創(chuàng)建了一個(gè)郵件地址的 Pattern,接著用這個(gè) Pattern 與多個(gè)郵件地址進(jìn)行匹配。當(dāng)程序中的 Matcher 為 null 時(shí),程序調(diào)用 matcher() 方法來(lái)創(chuàng)建一個(gè) Matcher 對(duì)象,一旦 Matcher 對(duì)象被創(chuàng)建,程序就調(diào)用 Matcher 的 reset() 方法將該 Matcher 應(yīng)用于新的字符序列。
從某個(gè)角度來(lái)看,Matcher 的 matches()、lookingAt() 和 String 類(lèi)的 equals() 有點(diǎn)相似。區(qū)別是 String 類(lèi)的 equals() 都是與字符串進(jìn)行比較,而 Matcher 的 matches() 和 lookingAt() 則是與正則表達(dá)式進(jìn)行匹配。
事實(shí)上,String 類(lèi)里也提供了 matches() 方法,該方法返回該字符串是否匹配指定的正則表達(dá)式。例如:
“kongyeeku@163.com”.matches("\w{3,20}@\w+\.(com|org|cn|net|gov)");// 返回 true
除此之外,還可以利用正則表達(dá)式對(duì)目標(biāo)字符串進(jìn)行分割、查找、替換等操作,看如下例子程序。
public class ReplaceTest {public static void main(String[] args) {String[] msgs = { "Java has regular expressions in 1.4", "regular expressions now expressing in Java","Java represses oracular expressions" };Pattern p = Pattern.compile("re\\w*");Matcher matcher = null;for (int i = 0; i < msgs.length; i++) {if (matcher == null) {matcher = p.matcher(msgs[i]);} else {matcher.reset(msgs[i]);}System.out.println(matcher.replaceAll("哈哈:)"));}} }上面程序使用了 Matcher 類(lèi)提供的 replaceAll() 把字符串中所有與正則表達(dá)式匹配的子串替換成“哈哈:)”,實(shí)際上,Matcher 類(lèi)還提供了一個(gè) replaceFirst(),該方法只替換第一個(gè)匹配的子串。運(yùn)行上面程序,會(huì)看到字符串中所有以“re”開(kāi)頭的單詞都會(huì)被替換成“哈哈:)”。
實(shí)際上,String 類(lèi)中也提供了 replaceAll()、replaceFirst()、split() 等方法。下面的例子程序直接使用 String 類(lèi)提供的正則表達(dá)式功能來(lái)進(jìn)行替換和分割。
public class StringReg {public static void main(String[] args) {String[] msgs = { "Java has regular expressions in 1.4", "regular expressions now expressing in Java","Java represses oracular expressions" };for (String msg : msgs) {System.out.println(msg.replaceFirst("re\\w*", "哈哈:)"));System.out.println(Arrays.toString(msg.split(" ")));}} }上面程序只使用 String 類(lèi)的 replaceFirst() 和 split() 方法對(duì)目標(biāo)字符串進(jìn)行了一次替換和分割。運(yùn)行上面程序,會(huì)看到如下所示的輸出結(jié)果。
Java has 哈哈:) expressions in 1.4 [Java, has, regular, expressions, in, 1.4] 哈哈:) expressions now expressing in Java [regular, expressions, now, expressing, in, Java] Java 哈哈:) oracular expressions [Java, represses, oracular, expressions]正則表達(dá)式是一個(gè)功能非常靈活的文本處理工具,增加了正則表達(dá)式支持后的 Java,可以不再使用 StringTokenizer 類(lèi)(也是一個(gè)處理字符串的工具,但功能遠(yuǎn)不如正則表達(dá)式強(qiáng)大)即可進(jìn)行復(fù)雜的字符串處理。
總結(jié)
以上是生活随笔為你收集整理的1.21 Pattern类和Matcher类的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 1.20 正则表达式详解
- 下一篇: 1.22 实例:正则表达式验证电话号码
