java.util.regex是一個用正則表達式所訂製的模式來對字符串進行匹配工做的類庫包。html
1.簡介: java
java.util.regex是一個用正則表達式所訂製的模式來對字符串進行匹配工做的類庫包。
它包括兩個類:Pattern和Matcher 。正則表達式
Pattern: 一個Pattern是一個正則表達式經編譯後的表現模式。 編程
Matcher: 一個Matcher對象是一個狀態機器,它依據Pattern對象作爲匹配模式對字符串展開匹配檢查。小程序
首先一個Pattern實例訂製了一個所用語法與PERL的相似的正則表達式經編譯後的模式,而後一個Matcher實例在這個給定的Pattern實例的模式控制下進行字符串的匹配工做。 app
如下咱們就分別來看看這兩個類:測試
2.Pattern類:
Pattern的方法以下:.net
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對象的。htm
如今咱們先來看一個簡單的例子,再經過分析它來了解怎樣生成一個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.
凱文已經看過《這個殺手不太冷》幾回了,由於它是一部好電影。/名詞:凱文。
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
}
}
輸出爲:
該次查找得到匹配組的數量爲: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
//檢測是否以"www."爲起始
p = Pattern.compile("^www.");
m = p.matcher(input);
if (m
//檢測是否包含非法字符
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.正則表達式規則:
http://edu.yesky.com/edupxpt/18/2143018.shtml
字符
x 字符 x
\\ 反斜線字符
\0n 八進制值的字符0n (0 <= n <= 7)
\0nn 八進制值的字符 0nn (0 <= n <= 7)
\0mnn 八進制值的字符0mnn 0mnn (0 <= m <= 3, 0 <= n <= 7)
\xhh 十六進制值的字符0xhh
\uhhhh 十六進制值的字符0xhhhh
\t 製表符('\u0009')
\n 換行符 ('\u000A')
\r 回車符 ('\u000D')
\f 換頁符 ('\u000C')
\a 響鈴符 ('\u0007')
\e 轉義符 ('\u001B')
\cx T對應於x的控制字符 x
字符類
[abc] a, b, or c (簡單類)
[^abc] 除了a、b或c以外的任意 字符(求反)
[a-zA-Z] a到z或A到Z ,包含(範圍)
[a-z-[bc]] a到z,除了b和c : [ad-z](減去)
[a-z-[m-p]] a到z,除了m到 p: [a-lq-z]
[a-z-[^def]] d, e, 或 f
備註:
方括號的正則表達式「t[aeio]n」只匹配「tan」、「Ten」、「tin」和「ton」,只能匹配單個字符。
圓括號,由於方括號只容許匹配單個字符;故匹配多個字符時使用圓括號「()」。好比使用「t(a|e|i|o|oo)n」正則表達式,就必須用圓括號。
預約義的字符類
. 任意字符(也許能與行終止符匹配,也許不能) 備註:句點符號表明任意一個字符。好比:表達式就是「t.n」,它匹配「tan」、「ten」、「tin」和「ton」,還匹配「t#n」、「tpn」甚至「t n」。
\d 數字: [0-9]
\D 非數字: [^0-9]
\s 空格符: [ \t\n\x0B\f\r]
\S 非空格符: [^\s]
\w 單詞字符: [a-zA-Z_0-9]
\W 非單詞字符: [^\w]
表達次數的符號符號 次數* 0次或者屢次+ 1次或者屢次? 0次或者1次{n} 剛好n次{n,m} 從n次到m次