很長時間以來,Unix管理用戶使用基于正則表達式的命令或程序,如grep、perl、sed和awk。由于這是一個非常強大的搜索和操縱字符串的手段,Java 1.4向核心API添加了java.util.regex程序包。當然,Java是與平臺無關的,這些正則表達式可以運行在任何系統(tǒng)上,而不僅僅是Unix。JDK中包含Regex程序包已有一段時間,但是我仍發(fā)現(xiàn)很多Java編程人員從未使用過它。Regex模式是一種有價值的基礎工具,可以用于很多類型的文本處理,如匹配、搜索、提取、替換和分析結(jié)構(gòu)化內(nèi)容。
在Java中,通過使用適當命名的Pattern類可以容易地確定String是否匹配某種模式。模式可以像匹配某個特定的String值那樣簡單,也可以很復雜,需要采用分組和字符類,如空白、數(shù)字、字母或控制符。由于它們是Java字符串并且基于Unicode(統(tǒng)一字符編碼),正則表達式也適用于國際化的應用程序。
正則式是最簡單的能準確匹配一個給定String的模式。換句話說,模式與所要匹配的文本是等價的。靜態(tài)的Pattern.matches方法用于比較一個String是否匹配一個給定模式。 以下的代碼將檢查變量data中的值是否與單詞“Java”相匹配:
String data = getStringData(); // populate the String somehow
boolean result = Pattern.matches("Java", data); // is it "Java"?
|
對于直接匹配字符串和簡單的模式而言,你很可能不會使用正則表達式,因為這實際上就是低效率版本的"Java".equals(data)。Regex的真正強大之處體現(xiàn)在使用包括字符類和量詞(*、+和?)的更復雜的模式上。目前已有很多優(yōu)秀的有關正則表達式模式的書籍,因此這里只討論模式的一些基本特性并重點討論Java的regex類和方法。為了快速了解這些特性,這里給出一些在正則表達式中使用的特殊字符,其中每一個均代表一類字符,在regex術(shù)語中它稱為字符類:
\d 數(shù)字
\D 非數(shù)字
\w 單字字符(0–9,A–Z,a–z,_ )
\W 非單字字符
\s 空白(空格符、換行符、回車鍵、制表符)
\S 非空白
[ ] 由方括號內(nèi)的一個字符列表創(chuàng)建的自定義字符類
. 匹配任何單個字符(除了換行符)
|
大多數(shù)字符在一個模式表達式中代表它們自己,但是一些字符有其特殊含義。上面使用的反斜杠(轉(zhuǎn)義字符)就是一個例子。下面的字符用于控制將一個子模式應用到匹配過程的次數(shù)。這些特殊字符的處理方式不同于其他字符:
? 重復前面的子模式零次或一次
* 重復前面的子模式零次或多次
+ 重復前面的子模式一次或多次
|
下面的正則表達式可以匹配任何對先輩的稱呼,如father、great-great-grandmother或great-great-great-grandfather。正如下面的示例所示,通過使用括弧中的子表達式可以創(chuàng)建更復雜的正則表達式:
((great–)*grand)?(mother|father)
|
接下來這個模式表達式將會匹配一個以一個數(shù)字開頭后跟零個或多個非空白字符的任意字符串(例如它將匹配“3”、“5x”和“56abcd9”,而不匹配“8 5”或“hello”):
要謹慎使用regex反斜杠字符,因為在Java中它也是String文字轉(zhuǎn)義字符。如果使用一個String文字來保存正則表達式,將需要通過使用兩個反斜杠來轉(zhuǎn)義反斜杠本身。例如:
String digitNonSpacePattern = "\\d\\S*";
String data = getStringData();
boolean isMatch = Pattern.matches(digitNonSpacePattern, data);
|
此外,模式匹配也內(nèi)置于String類本身。在String類中有一個新的簡便方法:matches。可以如下重寫以上的代碼:
boolean isMatch = getStringData().matches("\\d\\S*");
|
Pattern.matches方法和String的matches方法都適合一次性使用,但是若重復使用它們的效率較低。通過使用靜態(tài)的Pattern.compile方法創(chuàng)建一個Pattern實例可以得到一個更高效的用于執(zhí)行多次匹配的編譯版本的模式。Pattern對象可以和java.util.regex.Matcher類協(xié)同工作。為了執(zhí)行復雜的匹配,需要創(chuàng)建Matcher(匹配器)。Matcher將一個模式表達式綁定到一個特定的字符串,以便執(zhí)行更高級的匹配操作。以下的代碼段編譯了一個匹配僅由單個字符組成的模式:
String data = getStringData();
Pattern namePattern = Pattern.compile("\\w+");
// get a Matcher to apply the pattern to the data
Matcher nameMatcher = namePattern.matcher(data);
boolean isMatch = nameMatcher.matches();
|
要記住matches方法將會對整個輸入字符串和模式進行匹配。如果希望檢查字符串是否僅以模式開頭,則可以使用lookingAt方法:
boolean startsWith = nameMatcher.lookingAt();
|
在以下幾個小節(jié)中將會討論其他一些匹配技術(shù),包括查找匹配一個模式的子串以及執(zhí)行文本替換。