字符串處理是許多程序中非常重要的一部分,它們可以用于文本顯示,數據表示,查找鍵和很多目的.在Unix下,用戶可以使用正則表達式的強健功能實現這些目的,從Java1.4起,Java核心API就引入了java.util.regex程序包,它是一種有價值的基礎工具,可以用于很多類型的文本處理,如匹配,搜索,提取和分析結構化內容.
java.util.regex介紹
java.util.regex是一個用正則表達式所訂制的模式來對字符串進行匹配工作的類庫包。它包括兩個類:Pattern和Matcher Pattern .
Pattern是一個正則表達式經編譯后的表現模式。
Matcher 一個Matcher對象是一個狀態機器,它依據Pattern對象做為匹配模式對字符串展開匹配檢查。首先一個Pattern實例訂制了一個所用語法與PERL的類似的正則表達式經編譯后的模式,然后一個Matcher實例在這個給定的Pattern實例的模式控制下進行字符串的匹配工作。
Pattern類
在java中,通過適當命名的Pattern類可以容易確定String是否匹配某種模式.模式可以象匹配某個特定的String那樣簡單,也可以很復雜,需要采用分組和字符類,如空白,數字,字母或控制符.因為Java字符串基于統一字符編碼(Unicode),正則表達式也適用于國際化的應用程序.
Pattern的方法
Pattern的方法如下: static Pattern compile(String regex)
將給定的正則表達式編譯并賦予給Pattern類
static Pattern compile(String regex, int flags)
同上,但增加flag參數的指定,可選的flag參數包括:CASE INSENSITIVE,MULTILINE,DOTALL,UNICODE CASE, CANON EQ
int flags()
返回當前Pattern的匹配flag參數.
Matcher matcher(CharSequence input)
生成一個給定命名的Matcher對象
static boolean matches(String regex, CharSequence input)
編譯給定的正則表達式并且對輸入的字串以該正則表達式為模開展匹配,該方法適合于該正則表達式只會使用一次的情況,也就是只進行一次匹配工作,因為這種情況下并不需要生成一個Matcher實例。
String pattern()
返回該Patter對象所編譯的正則表達式。
String[] split(CharSequence input)
將目標字符串按照Pattern里所包含的正則表達式為模進行分割。
String[] split(CharSequence input, int limit)
作用同上,增加參數limit目的在于要指定分割的段數,如將limi設為2,那么目標字符串將根據正則表達式分為割為兩段。
一個正則表達式,也就是一串有特定意義的字符,必須首先要編譯成為一個Pattern類的實例,這個Pattern對象將會使用matcher()方法來生成一個Matcher實例,接著便可以使用該 Matcher實例以編譯的正則表達式為基礎對目標字符串進行匹配工作,多個Matcher是可以共用一個Pattern對象的。
Matcher的方法
Matcher appendReplacement(StringBuffer sb, String replacement)
將當前匹配子串替換為指定字符串,并且將替換后的子串以及其之前到上次匹配子串之后的字符串段添加到一個StringBuffer對象里。
StringBuffer appendTail(StringBuffer sb)
將最后一次匹配工作后剩余的字符串添加到一個StringBuffer對象里。
int end()
返回當前匹配的子串的最后一個字符在原目標字符串中的索引位置 。
int end(int group)
返回與匹配模式里指定的組相匹配的子串最后一個字符的位置。
boolean find()
嘗試在目標字符串里查找下一個匹配子串。
boolean find(int start)
重設Matcher對象,并且嘗試在目標字符串里從指定的位置開始查找下一個匹配的子串。
String group()
返回當前查找而獲得的與組匹配的所有子串內容
String group(int group)
返回當前查找而獲得的與指定的組匹配的子串內容
int groupCount()
返回當前查找所獲得的匹配組的數量。
boolean lookingAt()
檢測目標字符串是否以匹配的子串起始。
boolean matches()
嘗試對整個目標字符展開匹配檢測,也就是只有整個目標字符串完全匹配時才返回真值。
Pattern pattern()
返回該Matcher對象的現有匹配模式,也就是對應的Pattern 對象。
String replaceAll(String replacement)
將目標字符串里與既有模式相匹配的子串全部替換為指定的字符串。
String replaceFirst(String replacement)
將目標字符串里第一個與既有模式相匹配的子串替換為指定的字符串。
Matcher reset()
重設該Matcher對象。
Matcher reset(CharSequence input)
重設該Matcher對象并且指定一個新的目標字符串。
int start()
返回當前查找所獲子串的開始字符在原目標字符串中的位置。
int start(int group)
返回當前查找所獲得的和指定組匹配的子串的第一個字符在原目標字符串中的位置。
一個Matcher實例是被用來對目標字符串進行基于既有模式(也就是一個給定的Pattern所編譯的正則表達式)進行匹配查找的,所有往 Matcher的輸入都是通過CharSequence接口提供的,這樣做的目的在于可以支持對從多元化的數據源所提供的數據進行匹配工作。
使用Pattern類檢驗字符匹配
正則式是最簡單的能準確匹配一個給定String的模式,模式與要匹配的文本是等價的.靜態的Pattern.matches方法用于比較一個String是否匹配一個給定模式.例程如下:
String data="java";
boolean result=Pattern.matches("java",data);
字符類和表示次數的特殊字符
對于單字符串比較而言,使用正則表達式沒有什么優勢.Regex的真正強大之處在于體現在包括字符類和量詞(*,+,?)的更復雜的模式上.
字符類包括:
\d 數字
\D 非數字
\w 單字字符(0-9,A-Z,a-z)
\W 非單字字符
\s 空白(空格符,換行符,回車符,制表符)
\S 非空白
[] 由方括號內的一個字符列表創建的自定義字符類
. 匹配任何單個字符
下面的字符將用于控制將一個子模式應用到匹配次數的過程.
? 重復前面的子模式0次到一次
* 重復前面的子模式0次或多次
+ 重復前面的子模式一次到多次
復雜匹配例一:重復次數匹配
String[] dataArr = { "moon", "mon", "moon", "mono" };
for (String str : dataArr) {
String patternStr="m(o+)n";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失敗");
}
}
模式是”m(o+)n”,它表示mn中間的o可以重復一次或多次,因此moon,mon,mooon能匹配成功,而mono在n后多了一個o,和模式匹配不上.
注:
+表示一次或多次;?表示0次或一次;*表示0次或多次.
復雜匹配二:單個字符匹配
String[] dataArr = { "ban", "ben", "bin", "bon" ,"bun","byn","baen"};
for (String str : dataArr) {
String patternStr="b[aeiou]n";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失敗");
}
}
注:方括號中只允許的單個字符,模式“b[aeiou]n”指定,只有以b開頭,n結尾,中間是a,e,i,o,u中任意一個的才能匹配上,所以數組的前五個可以匹配,后兩個元素無法匹配.
方括號[]表示只有其中指定的字符才能匹配.
復雜匹配三:多個字符匹配
String[] dataArr = { "been", "bean", "boon", "buin" ,"bynn"};
for (String str : dataArr) {
String patternStr="b(ee|ea|oo)n";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失敗");
}
}
如果需要匹配多個字符,那么[]就不能用上了,這里我們可以用()加上|來代替,()表示一組,|表示或的關系,模式b(ee|ea|oo)n就能匹配been,bean,boon等.
因此前三個能匹配上,而后兩個不能.
復雜匹配四:數字匹配
String[] dataArr = { "1", "10", "101", "1010" ,"100+"};
for (String str : dataArr) {
String patternStr="\\d+";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失敗");
}
}
注:從前面可以知道,\\d表示的是數字,而+表示一次或多次,所以模式\\d+就表示一位或多位數字.
因此前四個能匹配上,最后一個因為+號是非數字字符而匹配不上.
復雜匹配五:字符數字混合匹配
String[] dataArr = { "a100", "b20", "c30", "df10000" ,"gh0t"};
for (String str : dataArr) {
String patternStr="\\w+\\d+";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失敗");
}
}
模式\\w+\\d+表示的是以多個單字字符開頭,多個數字結尾的字符串,因此前四個能匹配上,最后一個因為數字后還含有單字字符而不能匹配.
使用正則表達式劈分字符串-使用字符串的split方法
String str="薪水,職位 姓名;年齡 性別";
String[] dataArr =str.split("[,\\s;]");
for (String strTmp : dataArr) {
System.out.println(strTmp);
}
String類的split函數支持正則表達式,上例中模式能匹配”,”,單個空格,”;”中的一個,split函數能把它們中任意一個當作分隔符,將一個字符串劈分成字符串數組.
使用Pattern劈分字符串
String str="2007年12月11日";
Pattern p = Pattern.compile("[年月日]");
String[] dataArr =p.split(str);
for (String strTmp : dataArr) {
System.out.println(strTmp);
}
Pattern是一個正則表達式經編譯后的表現模式 ,它的split方法能有效劈分字符串.
注意其和String.split()使用上的不同.
使用正則表達式進行字符串替換
String str="10元 1000人民幣 10000元 100000RMB";
str=str.replaceAll("(\\d+)(元|人民幣|RMB)", "$1¥");
System.out.println(str);
上例中,模式“(\\d+)(元|人民幣|RMB)”按括號分成了兩組,第一組\\d+匹配單個或多個數字,第二組匹配元,人民幣,RMB中的任意一個,替換部分$1表示第一個組匹配的部分不變,其余組替換成¥.
替換后的str為¥10 ¥1000 ¥10000 ¥100000
使用matcher進行替換
Pattern p = Pattern.compile("m(o+)n",Pattern.CASE_INSENSITIVE);
// 用Pattern類的matcher()方法生成一個Matcher對象
Matcher m = p.matcher("moon mooon Mon mooooon Mooon");
StringBuffer sb = new StringBuffer();
// 使用find()方法查找第一個匹配的對象
boolean result = m.find();
// 使用循環找出模式匹配的內容替換之,再將內容加到sb里
while (result) {
m.appendReplacement(sb, "moon");
result = m.find();
}
// 最后調用appendTail()方法將最后一次匹配后的剩余字符串加到sb里;
m.appendTail(sb);
System.out.println("替換后內容是" + sb.toString());
使用Mather驗證IP地址的有效性
驗證函數:
public static boolean isValidIpAddr(String ipAddr){
String regx="(\\d+).(\\d+).(\\d+) .(\\d+)";
if(Pattern.matches(regx, ipAddr)){
Pattern pattern=Pattern.compile(regx);
Matcher mather=pattern.matcher(ipAddr);
while(mather.find()){
for(int i=1;i<=mather.groupCount();i++){
String str=mather.group(i);
int temp=Integer.parseInt(str);
if(temp>255 || temp<1){
return false;
}
}
}
}
else{
return false;
}
return true;
}
執行語句:
String[] ipArr = { "1.2.3.4", "3.2.1.5", "999.244.17.200", "233.200.18.20",
"2.1.0.18", "0.2.1.19" };
for (String str : ipArr) {
if (isValidIpAddr(str)) {
System.out.println(str + "是合法的IP地址");
} else {
System.out.println(str + "不是合法的IP地址");
}
}
執行結果:
1.2.3.4是合法的IP地址
3.2.1.5是合法的IP地址
999.244.17.200不是合法的IP地址
233.200.18.20是合法的IP地址
2.1.0.18不是合法的IP地址
0.2.1.19不是合法的IP地址