Pattern類定義
public final class Pattern extends Object implementsSerializable正規表達式的編譯表示形式。用于編譯正規表達式後建立一個比對模式。
指定為字元串的正規表達式必須首先被編譯為此類的執行個體。然後,可将得到的模式用于建立Matcher對象,依照正規表達式,該對象可以與任意字元序列比對。執行比對所涉及的所有狀态都駐留在比對器中,是以多個比對器可以共享同一模式。
是以,典型的調用順序是:
Pattern p =Pattern.compile("a*b");
Matcher m =p.matcher("aaaaab");
boolean b = m.matches();
在僅使用一次正規表達式時,可以友善地通過此類定義matches方法。此方法編譯表達式并在單個調用中将輸入序列與其比對。語句:
boolean b =Pattern.matches("a*b", "aaaaab");
等效于上面的三個語句,盡管對于重複的比對而言它效率不高,因為它不允許重用已編譯的模式。
此類的執行個體是不可變的,可供多個并發線程安全使用。Matcher類的執行個體用于此目的則不安全。
Pattern類方法詳解
1、Pattern complie(String regex):編譯正規表達式,并建立Pattern類。
由于Pattern的構造函數是私有的,不可以直接建立,是以通過靜态的簡單工廠方法compile(String regex)方法來建立,将給定的正規表達式編譯并賦予給Pattern類。
2、String pattern():傳回正規表達式的字元串形式。
其實就是傳回Pattern.complile(Stringregex)的regex參數。示例如下:
String regex ="\\?|\\*";
Pattern pattern= Pattern.compile(regex);
StringpatternStr = pattern.pattern();//傳回\?\*
3、Pattern compile(String regex, int flags)。
方法功能和compile(Stringregex)相同,不過增加了flag參數,flag參數用來控制正規表達式的比對行為,可取值範圍如下:
Pattern.CANON_EQ:啟用規範等價。當且僅當兩個字元的“正規分解(canonicaldecomposition)”都完全相同的情況下,才認定比對。預設情況下,不考慮“規範相等性(canonical equivalence)”。
Pattern.CASE_INSENSITIVE:啟用不區分大小寫的比對。預設情況下,大小寫不敏感的比對隻适用于US-ASCII字元集。這個标志能讓表達式忽略大小寫進行比對,要想對Unicode字元進行大小不敏感的比對,隻要将UNICODE_CASE與這個标志合起來就行了。
Pattern.COMMENTS:模式中允許空白和注釋。在這種模式下,比對時會忽略(正規表達式裡的)空格字元(不是指表達式裡的“\s”,而是指表達式裡的空格,tab,回車之類)。注釋從#開始,一直到這行結束。可以通過嵌入式的标志來啟用Unix行模式。
Pattern.DOTALL:啟用dotall模式。在這種模式下,表達式‘.’可以比對任意字元,包括表示一行的結束符。預設情況下,表達式‘.’不比對行的結束符。
Pattern.LITERAL:啟用模式的字面值解析。
Pattern.MULTILINE:啟用多行模式。在這種模式下,‘\^’和‘$’分别比對一行的開始和結束。此外,‘^’仍然比對字元串的開始,‘$’也比對字元串的結束。預設情況下,這兩個表達式僅僅比對字元串的開始和結束。
Pattern.UNICODE_CASE:啟用Unicode感覺的大小寫折疊。在這個模式下,如果你還啟用了CASE_INSENSITIVE标志,那麼它會對Unicode字元進行大小寫不敏感的比對。預設情況下,大小寫不敏感的比對隻适用于US-ASCII字元集。
Pattern.UNIX_LINES: 啟用Unix行模式。在這個模式下,隻有‘\n’才被認作一行的中止,并且與‘.’、‘^’、以及‘$’進行比對。
4、int flags():傳回目前Pattern的比對flag參數。
5、String[] split(CharSequence input)。
Pattern有一個split(CharSequenceinput)方法,用于分隔字元串,并傳回一個String[]。此外String[] split(CharSequence input, int limit)功能和String[]split(CharSequence input)相同,增加參數limit目的在于要指定分割的段數。
6、static boolean matches(String regex, CharSequenceinput)。
是一個靜态方法,用于快速比對字元串,該方法适合用于隻比對一次,且比對全部字元串。方法編譯給定的正規表達式并且對輸入的字串以該正規表達式為模式開展比對,該方法隻進行一次比對工作,并不需要生成一個Matcher執行個體。
7、Matcher matcher(CharSequence input)。
Pattern.matcher(CharSequenceinput)傳回一個Matcher對象。Matcher類的構造方法也是私有的,不能随意建立,隻能通過Pattern.matcher(CharSequence input)方法得到該類的執行個體。Pattern類隻能做一些簡單的比對操作,要想得到更強更便捷的正則比對操作,那就需要将Pattern與Matcher一起合作。Matcher類提供了對正規表達式的分組支援,以及對正規表達式的多次比對支援。
Java代碼示例:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("22bb23");
// 傳回p也就是傳回該Matcher對象是由哪個Pattern對象的建立的
m.pattern();
Pattern類使用示例:
package com.zxt.regex;
import java.util.regex.Pattern;
public classPatternTest {
public static void main(String[] args) {
// 使用Pattern.compile方法編譯一個正規表達式,建立一個比對模式
Patternpattern = Pattern.compile("\\?|\\*");
// pattern()函數傳回正規表達式的字元串形式傳回\?\*
StringpatternStr = pattern.pattern();
System.out.println(patternStr);
// flags()傳回目前Pattern的比對flag參數,這裡并沒有定義
int flag = pattern.flags();
System.out.println(flag);
// split方法對字元串進行分割
// 123 123 456 456
String[]splitStrs = pattern.split("123?123*456*456");
for (int i = 0; i < splitStrs.length; i++) {
System.out.print(splitStrs[i] + " ");
}
System.out.println();
// 123 123*456*456
String[]splitStrs2 = pattern.split("123?123*456*456",2);
for (int i = 0; i < splitStrs2.length; i++) {
System.out.print(splitStrs2[i] + " ");
}
System.out.println();
Patternp = Pattern.compile("\\d+");
String[]str = p.split("我的QQ是:456456我的電話是:0532214我的郵箱是:[email protected]");
for (int i = 0; i < str.length; i++) {
System.out.printf("str[%d] = %s\n",i, str[i]);
}
System.out.println();
// Pattern.matches用給定的模式對字元串進行一次比對,(需要全比對時才傳回true)
System.out.println("Pattern.matches(\"\\\\d+\",\"2223\") is " + Pattern.matches("\\d+", "2223"));
// 傳回false,需要比對到所有字元串才能傳回true,這裡aa不能比對到
System.out.println("Pattern.matches(\"\\\\d+\", \"2223aa\")is " + Pattern.matches("\\d+", "2223aa"));
// 傳回false,需要比對到所有字元串才能傳回true,這裡bb不能比對到
System.out.println("Pattern.matches(\"\\\\d+\",\"22bb23\") is " + Pattern.matches("\\d+", "22bb23"));
}
}
Matcher類定義
public final class Matcher extends Object implementsMatchResult通過調用模式(Pattern)的matcher方法從模式建立比對器。建立比對器後,可以使用它執行三種不同的比對操作:
1、matches方法嘗試将整個輸入序列與該模式比對。
2、lookingAt嘗試将輸入序列從頭開始與該模式比對。
3、find方法掃描輸入序列以查找與該模式比對的下一個子序列。
每個方法都傳回一個表示成功或失敗的布爾值。通過查詢比對器的狀态可以擷取關于成功比對的更多資訊。
比對器在其輸入的子集(稱為區域)中查找比對項。預設情況下,此區域包含全部的比對器輸入。可通過region方法修改區域,通過regionStart和regionEnd方法查詢區域。區域邊界與某些模式構造互動的方式是可以更改的。
此類還定義使用新字元串替換比對子序列的方法,需要時,可以從比對結果計算出新字元串的内容。可以先後使用appendReplacement和appendTail方法将結果收集到現有的字元串緩沖區,或者使用更加便捷的replaceAll方法建立一個可以在其中替換輸入序列中每個比對子序列的字元串。
比對器的顯式狀态包括最近成功比對的開始和結束索引。它還包括模式中每個捕獲組捕獲的輸入子序列的開始和結束索引以及該子序列的總數。出于友善的考慮,還提供了以字元串的形式傳回這些已捕獲子序列的方法。
比對器的顯式狀态最初是未定義的;在成功比對導緻IllegalStateException抛出之前嘗試查詢其中的任何部分。每個比對操作都将重新計算比對器的顯式狀态。比對器的隐式狀态包括輸入字元序列和添加位置,添加位置最初是零,然後由appendReplacement方法更新。
可以通過調用比對器的reset()方法來顯式重置比對器,如果需要新輸入序列,則調用其reset(CharSequence)方法。重置比對器将放棄其顯式狀态資訊并将添加位置設定為零。
此類的執行個體用于多個并發線程是不安全的。
Matcher類方法詳解
1、Matcher類提供了三個比對操作方法,三個方法均傳回boolean類型,當比對到時傳回true,沒比對到則傳回false。
boolean matches()最常用方法:嘗試對整個目标字元展開比對檢測,也就是隻有整個目标字元串完全比對時才傳回真值。
boolean lookingAt()對前面的字元串進行比對,隻有比對到的字元串在最前面才會傳回true。
boolean find():對字元串進行比對,比對到的字元串可以在任何位置。
2、傳回比對器的顯示狀态:intstart():傳回目前比對到的字元串在原目标字元串中的位置;int end():傳回目前比對的字元串的最後一個字元在原目标字元串中的索引位置;String group():傳回比對到的子字元串。
3、int start(),int end(),int group()均有一個重載方法,它們分别是int start(int i),int end(int i),int group(int i)專用于分組操作,Mathcer類還有一個groupCount()用于傳回有多少組。
4、Matcher類同時提供了四個将比對子串替換成指定字元串的方法:
1)、String replaceAll(Stringreplacement):将目标字元串裡與既有模式相比對的子串全部替換為指定的字元串。
2)、String replaceFirst(Stringreplacement):将目标字元串裡第一個與既有模式相比對的子串替換為指定的字元串。
3)、還有兩個方法Matcher appendReplacement(StringBuffersb, String replacement) 和StringBufferappendTail(StringBuffer sb)也很重要,appendReplacement允許直接将比對的字元串儲存在另一個StringBuffer中并且是漸進式比對,并不是隻比對一次或比對全部,而appendTail則是将未比對到的餘下的字元串添加到StringBuffer中。
5、其他一些方法:例如Matcherreset():重設該Matcher對象。
Matcher reset(CharSequence input):重設該Matcher對象并且指定一個新的目标字元串。
Matcher region(int start, int end):設定此比對器的區域限制。
Matcher類使用示例:
package com.zxt.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public classMatcherTest {
public static void main(String[] args) {
Patternp = Pattern.compile("\\d+");
// matches()對整個字元串進行比對
// 傳回false,因為bb不能被\d+比對,導緻整個字元串比對未成功。
Matcherm = p.matcher("22bb23");
System.out.println(m.matches());
m = p.matcher("2223");
// 傳回true,因為\d+比對到了整個字元串
System.out.println(m.matches());
// lookingAt()對字元串字首進行比對
m = p.matcher("22bb23");
// 傳回true,因為\d+比對到了前面的22
System.out.println(m.lookingAt());
m = p.matcher("aa2223");
// 傳回false,因為\d+不能比對前面的aa
System.out.println(m.lookingAt());
// find()對字元串進行比對,比對到的字元串可以在任何位置。
m = p.matcher("22bb23");
System.out.println(m.find()); // true
m = p.matcher("aa2223");
System.out.println(m.find()); // true
m = p.matcher("aabb");
System.out.println(m.find()); // false
// 當比對器比對失敗時,使用傳回比對器狀态的方法将出錯,例如:m.start();
m = p.matcher("aa2223bb");
System.out.println(m.find()); // true
System.out.println(m.start()); // 2
System.out.println(m.end()); // 6
System.out.println(m.group()); // 2223
p = Pattern.compile("([a-z]+)(\\d+)");
m = p.matcher("aaa2223bb");
// 比對aaa2223
m.find();
// 傳回2,因為有2組
System.out.println(m.groupCount());
// 傳回0, 傳回第一組比對到的子字元串在字元串中的索引号
System.out.println(m.start(1));
// 傳回3
System.out.println(m.start(2));
// 傳回3 傳回第一組比對到的子字元串的最後一個字元在字元串中的索引位置.
System.out.println(m.end(1));
// 傳回2223,傳回第二組比對到的子字元串
System.out.println(m.group(2));
}
}
應用執行個體
1、一個簡單的郵箱驗證小程式
package com.zxt.regex;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 一個簡單的郵件位址比對程式
*/
public classEmailMatch {
public static void main(String[] args) throws Exception {
Scannersc = new Scanner(System.in);
while (sc.hasNext()) {
Stringinput = sc.nextLine();
// 檢測輸入的EMAIL位址是否以非法符号"."或"@"作為起始字元
Patternp = Pattern.compile("^@");
Matcherm = p.matcher(input);
if (m.lookingAt()) {
System.out.println("EMAIL位址不能以'@'作為起始字元");
}
// 檢測是否以"www."為起始
p = Pattern.compile("^www.");
m = p.matcher(input);
if (m.lookingAt()) {
System.out.println("EMAIL位址不能以'www.'起始");
}
// 檢測是否包含非法字元
p = Pattern.compile("[^[email protected]_-~#]+");
m = p.matcher(input);
StringBuffersb = new StringBuffer();
boolean result = m.find();
boolean deletedIllegalChars= false;
while (result) {
// 如果找到了非法字元那麼就設下标記
deletedIllegalChars= true;
// 如果裡面包含非法字元如冒号雙引号等,那麼就把他們消去,加到SB裡面
m.appendReplacement(sb, "");
result = m.find();
}
// 此方法從添加位置開始從輸入序列讀取字元,并将其添加到給定字元串緩沖區。
// 可以在一次或多次調用 appendReplacement 方法後調用它來複制剩餘的輸入序列。
m.appendTail(sb);
if (deletedIllegalChars){
System.out.println("輸入的EMAIL位址裡包含有冒号、逗号等非法字元,請修改");
System.out.println("您現在的輸入為: " + input);
System.out.println("修改後合法的位址應類似: " + sb.toString());
}
}
sc.close();
}
}
2、判斷身份證:要麼是15位,要麼是18位,最後一位可以為字母,并寫程式提出其中的年月日。
可以使用正規表達式來定義複雜的字元串格式:(\d{17}[0-9a-zA-Z]|\d{14}[0-9a-zA-Z])可以用來判斷是否為合法的15位或18位身份證号碼。因為15位和18位的身份證号碼都是從7位到第12位為身份證為日期類型。這樣我們可以設計出更精确的正則模式,提取身份證号中的日期資訊。
package com.zxt.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public classIdentityMatch {
public static void main(String[] args) {
// 測試是否為合法的身份證号碼
String[]id_cards = { "130681198712092019","13068119871209201x","13068119871209201","123456789012345",
"12345678901234x","1234567890123"};
// 測試是否為合法身份證的正規表達式
Patternpattern = Pattern.compile("(\\d{17}[0-9a-zA-Z]|\\d{14}[0-9a-zA-Z])");
// 用于提取出生日字元串的正規表達式
Patternpattern1 = Pattern.compile("\\d{6}(\\d{8}).*");
// 用于将生日字元串分解為年月日的正規表達式
Patternpattern2 = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");
Matchermatcher = pattern.matcher("");
for (int i = 0; i < id_cards.length; i++) {
matcher.reset(id_cards[i]);
System.out.println(id_cards[i] + " is id cards:" + matcher.matches());
// 如果它是一個合法的身份證号,提取出出生的年月日
if (matcher.matches()) {
Matchermatcher1 = pattern1.matcher(id_cards[i]);
matcher1.lookingAt();
Stringbirthday = matcher1.group(1);
Matchermatcher2 = pattern2.matcher(birthday);
if (matcher2.find()) {
System.out.println("它對應的出生年月日為:" + matcher2.group(1) + "年" + matcher2.group(2) + "月"
+matcher2.group(3) + "日");
}
}
System.out.println();
}
}
}