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