?java正則表達式
<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script> 現在JDK1.4里終于有了自己的正則表達式API包,JAVA程序員可以免去找第三方提供的正則表達式庫的周折了,我們現在就馬上來了解一下這個SUN提供的遲來恩物-?-對我來說確實如此。
1.簡介:?
java.util.regex是一個用正則表達式所訂制的模式來對字符串進行匹配工作的類庫包。
它包括兩個類:Pattern和Matcher?Pattern?一個Pattern是一個正則表達式經編譯后的表現模式。?
Matcher?一 個Matcher對象是一個狀態機器,它依據Pattern對象做為匹配模式對字符串展開匹配檢查。?首先一個Pattern實例訂制了一個所用語法與 PERL的類似的正則表達式經編譯后的模式,然后一個Matcher實例在這個給定的Pattern實例的模式控制下進行字符串的匹配工作。
以下我們就分別來看看這兩個類:
2.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對象的。
現在我們先來看一個簡單的例子,再通過分析它來了解怎樣生成一個Pattern對象并且編譯一個正則表達式,最后根據這個正則表達式將目標字符串進行分割:?
import?java.util.regex.*;
public?class?Replacement{
??????public?static?void?main(String[]?args)?throws?Exception?{
????????//?生成一個Pattern,同時編譯一個正則表達式
????????Pattern?p?=?Pattern.compile("[/]+");
????????//用Pattern的split()方法把字符串按"/"分割
????????String[]?result?=?p.split(
"Kevin?has?seen《LEON》seveal?times,because?it?is?a?good?film."
+"/?凱文已經看過《這個殺手不太冷》幾次了,因為它是一部"
+"好電影。/名詞:凱文。");
????????for?(int?i=0;?i<result.length; i++)
System.out.println(result[i]);
}
}
輸出結果為:
Kevin has seen《LEON》seveal times,because it is a good film.
凱文已經看過《這個殺手不太冷》幾次了,因為它是一部好電影。
名詞:凱文。
很明顯,該程序將字符串按"/"進行了分段,我們以下再使用 split(CharSequence input, int limit)方法來指定分段的段數,程序改動為:
tring[] result = p.split("Kevin has seen《LEON》seveal times,because it is a good film./ 凱文已經看過《這個殺手不太冷》幾次了,因為它是一部好電影。/名詞:凱文。",2);
這里面的參數"2"表明將目標語句分為兩段。
輸出結果則為:
Kevin has seen《LEON》seveal times,because it is a good film.
凱文已經看過《這個殺手不太冷》幾次了,因為它是一部好電影。/名詞:凱文。
由 上面的例子,我們可以比較出java.util.regex包在構造Pattern對象以及編譯指定的正則表達式的實現手法與我們在上一篇中所介紹的 Jakarta-ORO 包在完成同樣工作時的差別,Jakarta-ORO 包要先構造一個PatternCompiler類對象接著生成一個Pattern對象,再將正則表達式用該PatternCompiler類的 compile()方法來將所需的正則表達式編譯賦予Pattern類:
PatternCompiler orocom=new Perl5Compiler();
Pattern pattern=orocom.compile("REGULAR EXPRESSIONS");
PatternMatcher matcher=new Perl5Matcher();
但是在java.util.regex包里,我們僅需生成一個Pattern類,直接使用它的compile()方法就可以達到同樣的效果:
Pattern p = Pattern.compile("[/]+");
因此似乎java.util.regex的構造法比Jakarta-ORO更為簡潔并容易理解。
3.Matcher類:
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接口提供的,這樣做的目的在于可以支持對從多元化的數據源所提供的數據進行匹配工作。
我們分別來看看各方法的使用:
★matches()/lookingAt ()/find():
一個Matcher對象是由一個Pattern對象調用其matcher()方法而生成的,一旦該Matcher對象生成,它就可以進行三種不同的匹配查找操作:
matches()方法嘗試對整個目標字符展開匹配檢測,也就是只有整個目標字符串完全匹配時才返回真值。
lookingAt ()方法將檢測目標字符串是否以匹配的子串起始。
find()方法嘗試在目標字符串里查找下一個匹配子串。
以上三個方法都將返回一個布爾值來表明成功與否。
★replaceAll ()/appendReplacement()/appendTail():
Matcher類同時提供了四個將匹配子串替換成指定字符串的方法:
replaceAll()
replaceFirst()
appendReplacement()
appendTail()
replaceAll()與replaceFirst()的用法都比較簡單,請看上面方法的解釋。我們主要重點了解一下appendReplacement()和appendTail()方法。
appendReplacement(StringBuffer sb, String replacement) 將當前匹配子串替換為指定字符串,并且將替換后的子串以及其之前到上次匹配子串之后的字符串段添加到一個StringBuffer對象里,而 appendTail(StringBuffer sb) 方法則將最后一次匹配工作后剩余的字符串添加到一個StringBuffer對象里。
例 如,有字符串fatcatfatcatfat,假設既有正則表達式模式為"cat",第一次匹配后調用 appendReplacement(sb,"dog"),那么這時StringBuffer sb的內容為fatdog,也就是fatcat中的cat被替換為dog并且與匹配子串前的內容加到sb里,而第二次匹配后調用 appendReplacement(sb,"dog"),那么sb的內容就變為fatdogfatdog,如果最后再調用一次 appendTail(sb),那么sb最終的內容將是fatdogfatdogfat。
還是有點模糊?那么我們來看個簡單的程序:
//該例將把句子里的"Kelvin"改為"Kevin"
import java.util.regex.*;
public class MatcherTest{
public static void main(String[] args)
throws Exception {
//生成Pattern對象并且編譯一個簡單的正則表達式"Kelvin"
Pattern p = Pattern.compile("Kevin");
//用Pattern類的matcher()方法生成一個Matcher對象
Matcher m = p.matcher("Kelvin Li and Kelvin Chan are both working in Kelvin Chen's KelvinSoftShop company");
StringBuffer sb = new StringBuffer();
int i=0;
//使用find()方法查找第一個匹配的對象
boolean result = m.find();
//使用循環將句子里所有的kelvin找出并替換再將內容加到sb里
while(result) {
i++;
m.appendReplacement(sb, "Kevin");
System.out.println("第"+i+"次匹配后sb的內容是:"+sb);
//繼續查找下一個匹配對象
result = m.find();
}
//最后調用appendTail()方法將最后一次匹配后的剩余字符串加到sb里;
m.appendTail(sb);
System.out.println("調用m.appendTail(sb)后sb的最終內容是:"+ sb.toString());
}
}
最終輸出結果為:
第1次匹配后sb的內容是:Kevin
第2次匹配后sb的內容是:Kevin Li and Kevin
第3次匹配后sb的內容是:Kevin Li and Kevin Chan are both working in Kevin
第4次匹配后sb的內容是:Kevin Li and Kevin Chan are both working in Kevin Chen's Kevin
調用m.appendTail(sb)后sb的最終內容是:Kevin Li and Kevin Chan are both working in Kevin Chen's KevinSoftShop company.
看了上面這個例程是否對appendReplacement(),appendTail()兩個方法的使用更清楚呢,如果還是不太肯定最好自己動手寫幾行代碼測試一下。
★group()/group(int group)/groupCount():
該系列方法與我們在上篇介紹的Jakarta-ORO中的MatchResult .group()方法類似(有關Jakarta-ORO請參考上篇的內容),都是要返回與組匹配的子串內容,下面代碼將很好解釋其用法:
import java.util.regex.*;
public class GroupTest{
public static void main(String[] args)
throws Exception {
Pattern p = Pattern.compile("(ca)(t)");
Matcher m = p.matcher("one cat,two cats in the yard");
StringBuffer sb = new StringBuffer();
boolean result = m.find();
System.out.println("該次查找獲得匹配組的數量為:"+m.groupCount());
for(int i=1;i<=m.groupCount();i++){
System.out.println("第"+i+"組的子串內容為: "+m.group(i));
}
}
}
輸出為:
該次查找獲得匹配組的數量為:2
第1組的子串內容為:ca
第2組的子串內容為:t
Matcher對象的其他方法因比較好理解且由于篇幅有限,請讀者自己編程驗證。
4.一個檢驗Email地址的小程序:
最后我們來看一個檢驗Email地址的例程,該程序是用來檢驗一個輸入的EMAIL地址里所包含的字符是否合法,雖然這不是一個完整的EMAIL地址檢驗程序,它不能檢驗所有可能出現的情況,但在必要時您可以在其基礎上增加所需功能。
import java.util.regex.*;
public class Email {
public static void main(String[] args) throws Exception {
String input = args[0];
//檢測輸入的EMAIL地址是否以 非法符號"."或"@"作為起始字符
Pattern p = Pattern.compile("^\\.|^\\@");
Matcher m = p.matcher(input);
if (m.find()){
System.err.println("EMAIL地址不能以'.'或'@'作為起始字符");
}
//檢測是否以"www."為起始
p = Pattern.compile("^www\\.");
m = p.matcher(input);
if (m.find()) {
System.out.println("EMAIL地址不能以'www.'起始");
}
//檢測是否包含非法字符
p = Pattern.compile("[^A-Za-z0-9\\.\\@_\\-~#]+");
m = p.matcher(input);
StringBuffer sb = new StringBuffer();
boolean result = m.find();
boolean deletedIllegalChars = false;
while(result) {
//如果找到了非法字符那么就設下標記
deletedIllegalChars = true;
//如果里面包含非法字符如冒號雙引號等,那么就把他們消去,加到SB里面
m.appendReplacement(sb, "");
result = m.find();
}
m.appendTail(sb);
input = sb.toString();
if (deletedIllegalChars) {
System.out.println("輸入的EMAIL地址里包含有冒號、逗號等非法字符,請修改");
System.out.println("您現在的輸入為: "+args[0]);
System.out.println("修改后合法的地址應類似: "+input);
}
}
}
例如,我們在命令行輸入:java Email www.kevin@163.net
那么輸出結果將會是:EMAIL地址不能以'www.'起始
如果輸入的EMAIL為@kevin@163.net
則輸出為:EMAIL地址不能以'.'或'@'作為起始字符
當輸入為:cgjmail#$%@163.net
那么輸出就是:
輸入的EMAIL地址里包含有冒號、逗號等非法字符,請修改
您現在的輸入為: cgjmail#$%@163.net
修改后合法的地址應類似: cgjmail@163.net
5.總結:
本 文介紹了jdk1.4.0-beta3里正則表達式庫--java.util.regex中的類以及其方法,如果結合與上一篇中所介紹的Jakarta- ORO API作比較,讀者會更容易掌握該API的使用,當然該庫的性能將在未來的日子里不斷擴展,希望獲得最新信息的讀者最好到及時到SUN的網站去了解。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
