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