Java Pattern與Matcher字符串匹配案例詳解
Pattern類定義
public final class Pattern extends Object implementsSerializable正則表達(dá)式的編譯表示形式。用于編譯正則表達(dá)式后創(chuàng)建一個(gè)匹配模式。
指定為字符串的正則表達(dá)式必須首先被編譯為此類的實(shí)例。然后,可將得到的模式用于創(chuàng)建Matcher對(duì)象,依照正則表達(dá)式,該對(duì)象可以與任意字符序列匹配。執(zhí)行匹配所涉及的所有狀態(tài)都駐留在匹配器中,所以多個(gè)匹配器可以共享同一模式。
因此,典型的調(diào)用順序是:
Pattern p =Pattern.compile("a*b");
Matcher m =p.matcher("aaaaab");
boolean b = m.matches();
在僅使用一次正則表達(dá)式時(shí),可以方便地通過此類定義matches方法。此方法編譯表達(dá)式并在單個(gè)調(diào)用中將輸入序列與其匹配。語句:
boolean b =Pattern.matches("a*b", "aaaaab");
等效于上面的三個(gè)語句,盡管對(duì)于重復(fù)的匹配而言它效率不高,因?yàn)樗辉试S重用已編譯的模式。
此類的實(shí)例是不可變的,可供多個(gè)并發(fā)線程安全使用。Matcher類的實(shí)例用于此目的則不安全。
Pattern類方法詳解
1、Pattern complie(String regex):編譯正則表達(dá)式,并創(chuàng)建Pattern類。
由于Pattern的構(gòu)造函數(shù)是私有的,不可以直接創(chuàng)建,所以通過靜態(tài)的簡單工廠方法compile(String regex)方法來創(chuàng)建,將給定的正則表達(dá)式編譯并賦予給Pattern類。
2、String pattern():返回正則表達(dá)式的字符串形式。
其實(shí)就是返回Pattern.complile(Stringregex)的regex參數(shù)。示例如下:
String regex ="\\?|\\*"; Pattern pattern= Pattern.compile(regex); StringpatternStr = pattern.pattern();//返回\?\*
3、Pattern compile(String regex, int flags)。
方法功能和compile(Stringregex)相同,不過增加了flag參數(shù),flag參數(shù)用來控制正則表達(dá)式的匹配行為,可取值范圍如下:
Pattern.CANON_EQ:啟用規(guī)范等價(jià)。當(dāng)且僅當(dāng)兩個(gè)字符的“正規(guī)分解(canonicaldecomposition)”都完全相同的情況下,才認(rèn)定匹配。默認(rèn)情況下,不考慮“規(guī)范相等性(canonical equivalence)”。
Pattern.CASE_INSENSITIVE:啟用不區(qū)分大小寫的匹配。默認(rèn)情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。這個(gè)標(biāo)志能讓表達(dá)式忽略大小寫進(jìn)行匹配,要想對(duì)Unicode字符進(jìn)行大小不敏感的匹配,只要將UNICODE_CASE與這個(gè)標(biāo)志合起來就行了。
Pattern.COMMENTS:模式中允許空白和注釋。在這種模式下,匹配時(shí)會(huì)忽略(正則表達(dá)式里的)空格字符(不是指表達(dá)式里的“\s”,而是指表達(dá)式里的空格,tab,回車之類)。注釋從#開始,一直到這行結(jié)束。可以通過嵌入式的標(biāo)志來啟用Unix行模式。
Pattern.DOTALL:啟用dotall模式。在這種模式下,表達(dá)式‘.'可以匹配任意字符,包括表示一行的結(jié)束符。默認(rèn)情況下,表達(dá)式‘.'不匹配行的結(jié)束符。
Pattern.LITERAL:啟用模式的字面值解析。
Pattern.MULTILINE:啟用多行模式。在這種模式下,‘\^'和‘$'分別匹配一行的開始和結(jié)束。此外,‘^'仍然匹配字符串的開始,‘$'也匹配字符串的結(jié)束。默認(rèn)情況下,這兩個(gè)表達(dá)式僅僅匹配字符串的開始和結(jié)束。
Pattern.UNICODE_CASE:啟用Unicode感知的大小寫折疊。在這個(gè)模式下,如果你還啟用了CASE_INSENSITIVE標(biāo)志,那么它會(huì)對(duì)Unicode字符進(jìn)行大小寫不敏感的匹配。默認(rèn)情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。
Pattern.UNIX_LINES: 啟用Unix行模式。在這個(gè)模式下,只有‘\n'才被認(rèn)作一行的中止,并且與‘.'、‘^'、以及‘$'進(jìn)行匹配。
4、int flags():返回當(dāng)前Pattern的匹配flag參數(shù)。
5、String[] split(CharSequence input)。
Pattern有一個(gè)split(CharSequenceinput)方法,用于分隔字符串,并返回一個(gè)String[]。此外String[] split(CharSequence input, int limit)功能和String[]split(CharSequence input)相同,增加參數(shù)limit目的在于要指定分割的段數(shù)。
6、static boolean matches(String regex, CharSequenceinput)。
是一個(gè)靜態(tài)方法,用于快速匹配字符串,該方法適合用于只匹配一次,且匹配全部字符串。方法編譯給定的正則表達(dá)式并且對(duì)輸入的字串以該正則表達(dá)式為模式開展匹配,該方法只進(jìn)行一次匹配工作,并不需要生成一個(gè)Matcher實(shí)例。
7、Matcher matcher(CharSequence input)。
Pattern.matcher(CharSequenceinput)返回一個(gè)Matcher對(duì)象。Matcher類的構(gòu)造方法也是私有的,不能隨意創(chuàng)建,只能通過Pattern.matcher(CharSequence input)方法得到該類的實(shí)例。Pattern類只能做一些簡單的匹配操作,要想得到更強(qiáng)更便捷的正則匹配操作,那就需要將Pattern與Matcher一起合作。Matcher類提供了對(duì)正則表達(dá)式的分組支持,以及對(duì)正則表達(dá)式的多次匹配支持。
Java代碼示例:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("22bb23");
// 返回p也就是返回該Matcher對(duì)象是由哪個(gè)Pattern對(duì)象的創(chuàng)建的
m.pattern();
Pattern類使用示例:
package com.zxt.regex;
import java.util.regex.Pattern;
public classPatternTest {
public static void main(String[] args) {
// 使用Pattern.compile方法編譯一個(gè)正則表達(dá)式,創(chuàng)建一個(gè)匹配模式
Patternpattern = Pattern.compile("\\?|\\*");
// pattern()函數(shù)返回正則表達(dá)式的字符串形式返回\?\*
StringpatternStr = pattern.pattern();
System.out.println(patternStr);
// flags()返回當(dāng)前Pattern的匹配flag參數(shù),這里并沒有定義
int flag = pattern.flags();
System.out.println(flag);
// split方法對(duì)字符串進(jìn)行分割
// 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我的郵箱是:aaa@aaa.com");
for (int i = 0; i < str.length; i++) {
System.out.printf("str[%d] = %s\n",i, str[i]);
}
System.out.println();
// Pattern.matches用給定的模式對(duì)字符串進(jìn)行一次匹配,(需要全匹配時(shí)才返回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通過調(diào)用模式(Pattern)的matcher方法從模式創(chuàng)建匹配器。創(chuàng)建匹配器后,可以使用它執(zhí)行三種不同的匹配操作:
1、matches方法嘗試將整個(gè)輸入序列與該模式匹配。
2、lookingAt嘗試將輸入序列從頭開始與該模式匹配。
3、find方法掃描輸入序列以查找與該模式匹配的下一個(gè)子序列。
每個(gè)方法都返回一個(gè)表示成功或失敗的布爾值。通過查詢匹配器的狀態(tài)可以獲取關(guān)于成功匹配的更多信息。
匹配器在其輸入的子集(稱為區(qū)域)中查找匹配項(xiàng)。默認(rèn)情況下,此區(qū)域包含全部的匹配器輸入??赏ㄟ^region方法修改區(qū)域,通過regionStart和regionEnd方法查詢區(qū)域。區(qū)域邊界與某些模式構(gòu)造交互的方式是可以更改的。
此類還定義使用新字符串替換匹配子序列的方法,需要時(shí),可以從匹配結(jié)果計(jì)算出新字符串的內(nèi)容??梢韵群笫褂胊ppendReplacement和appendTail方法將結(jié)果收集到現(xiàn)有的字符串緩沖區(qū),或者使用更加便捷的replaceAll方法創(chuàng)建一個(gè)可以在其中替換輸入序列中每個(gè)匹配子序列的字符串。
匹配器的顯式狀態(tài)包括最近成功匹配的開始和結(jié)束索引。它還包括模式中每個(gè)捕獲組捕獲的輸入子序列的開始和結(jié)束索引以及該子序列的總數(shù)。出于方便的考慮,還提供了以字符串的形式返回這些已捕獲子序列的方法。
匹配器的顯式狀態(tài)最初是未定義的;在成功匹配導(dǎo)致IllegalStateException拋出之前嘗試查詢其中的任何部分。每個(gè)匹配操作都將重新計(jì)算匹配器的顯式狀態(tài)。匹配器的隱式狀態(tài)包括輸入字符序列和添加位置,添加位置最初是零,然后由appendReplacement方法更新。
可以通過調(diào)用匹配器的reset()方法來顯式重置匹配器,如果需要新輸入序列,則調(diào)用其reset(CharSequence)方法。重置匹配器將放棄其顯式狀態(tài)信息并將添加位置設(shè)置為零。
此類的實(shí)例用于多個(gè)并發(fā)線程是不安全的。
Matcher類方法詳解
1、Matcher類提供了三個(gè)匹配操作方法,三個(gè)方法均返回boolean類型,當(dāng)匹配到時(shí)返回true,沒匹配到則返回false。
boolean matches()最常用方法:嘗試對(duì)整個(gè)目標(biāo)字符展開匹配檢測,也就是只有整個(gè)目標(biāo)字符串完全匹配時(shí)才返回真值。
boolean lookingAt()對(duì)前面的字符串進(jìn)行匹配,只有匹配到的字符串在最前面才會(huì)返回true。
boolean find():對(duì)字符串進(jìn)行匹配,匹配到的字符串可以在任何位置。
2、返回匹配器的顯示狀態(tài):intstart():返回當(dāng)前匹配到的字符串在原目標(biāo)字符串中的位置;int end():返回當(dāng)前匹配的字符串的最后一個(gè)字符在原目標(biāo)字符串中的索引位置;String group():返回匹配到的子字符串。
3、int start(),int end(),int group()均有一個(gè)重載方法,它們分別是int start(int i),int end(int i),int group(int i)專用于分組操作,Mathcer類還有一個(gè)groupCount()用于返回有多少組。
4、Matcher類同時(shí)提供了四個(gè)將匹配子串替換成指定字符串的方法:
1)、String replaceAll(Stringreplacement):將目標(biāo)字符串里與既有模式相匹配的子串全部替換為指定的字符串。
2)、String replaceFirst(Stringreplacement):將目標(biāo)字符串里第一個(gè)與既有模式相匹配的子串替換為指定的字符串。
3)、還有兩個(gè)方法Matcher appendReplacement(StringBuffersb, String replacement) 和StringBufferappendTail(StringBuffer sb)也很重要,appendReplacement允許直接將匹配的字符串保存在另一個(gè)StringBuffer中并且是漸進(jìn)式匹配,并不是只匹配一次或匹配全部,而appendTail則是將未匹配到的余下的字符串添加到StringBuffer中。
5、其他一些方法:例如Matcherreset():重設(shè)該Matcher對(duì)象。
Matcher reset(CharSequence input):重設(shè)該Matcher對(duì)象并且指定一個(gè)新的目標(biāo)字符串。
Matcher region(int start, int end):設(shè)置此匹配器的區(qū)域限制。
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()對(duì)整個(gè)字符串進(jìn)行匹配
// 返回false,因?yàn)閎b不能被\d+匹配,導(dǎo)致整個(gè)字符串匹配未成功。
Matcherm = p.matcher("22bb23");
System.out.println(m.matches());
m = p.matcher("2223");
// 返回true,因?yàn)閈d+匹配到了整個(gè)字符串
System.out.println(m.matches());
// lookingAt()對(duì)字符串前綴進(jìn)行匹配
m = p.matcher("22bb23");
// 返回true,因?yàn)閈d+匹配到了前面的22
System.out.println(m.lookingAt());
m = p.matcher("aa2223");
// 返回false,因?yàn)閈d+不能匹配前面的aa
System.out.println(m.lookingAt());
// find()對(duì)字符串進(jìn)行匹配,匹配到的字符串可以在任何位置。
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
// 當(dāng)匹配器匹配失敗時(shí),使用返回匹配器狀態(tài)的方法將出錯(cuò),例如: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,因?yàn)橛?組
System.out.println(m.groupCount());
// 返回0, 返回第一組匹配到的子字符串在字符串中的索引號(hào)
System.out.println(m.start(1));
// 返回3
System.out.println(m.start(2));
// 返回3 返回第一組匹配到的子字符串的最后一個(gè)字符在字符串中的索引位置.
System.out.println(m.end(1));
// 返回2223,返回第二組匹配到的子字符串
System.out.println(m.group(2));
}
}
應(yīng)用實(shí)例
1、一個(gè)簡單的郵箱驗(yàn)證小程序
package com.zxt.regex;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 一個(gè)簡單的郵件地址匹配程序
*/
public classEmailMatch {
public static void main(String[] args) throws Exception {
Scannersc = new Scanner(System.in);
while (sc.hasNext()) {
Stringinput = sc.nextLine();
// 檢測輸入的EMAIL地址是否以非法符號(hào)"."或"@"作為起始字符
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("[^A-Za-z0-9.@_-~#]+");
m = p.matcher(input);
StringBuffersb = new StringBuffer();
boolean result = m.find();
boolean deletedIllegalChars= false;
while (result) {
// 如果找到了非法字符那么就設(shè)下標(biāo)記
deletedIllegalChars= true;
// 如果里面包含非法字符如冒號(hào)雙引號(hào)等,那么就把他們消去,加到SB里面
m.appendReplacement(sb, "");
result = m.find();
}
// 此方法從添加位置開始從輸入序列讀取字符,并將其添加到給定字符串緩沖區(qū)。
// 可以在一次或多次調(diào)用 appendReplacement 方法后調(diào)用它來復(fù)制剩余的輸入序列。
m.appendTail(sb);
if (deletedIllegalChars){
System.out.println("輸入的EMAIL地址里包含有冒號(hào)、逗號(hào)等非法字符,請(qǐng)修改");
System.out.println("您現(xiàn)在的輸入為: " + input);
System.out.println("修改后合法的地址應(yīng)類似: " + sb.toString());
}
}
sc.close();
}
}

2、判斷身份證:要么是15位,要么是18位,最后一位可以為字母,并寫程序提出其中的年月日。
可以使用正則表達(dá)式來定義復(fù)雜的字符串格式:(\d{17}[0-9a-zA-Z]|\d{14}[0-9a-zA-Z])可以用來判斷是否為合法的15位或18位身份證號(hào)碼。因?yàn)?5位和18位的身份證號(hào)碼都是從7位到第12位為身份證為日期類型。這樣我們可以設(shè)計(jì)出更精確的正則模式,提取身份證號(hào)中的日期信息。
package com.zxt.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public classIdentityMatch {
public static void main(String[] args) {
// 測試是否為合法的身份證號(hào)碼
String[]id_cards = { "130681198712092019","13068119871209201x","13068119871209201","123456789012345",
"12345678901234x","1234567890123"};
// 測試是否為合法身份證的正則表達(dá)式
Patternpattern = Pattern.compile("(\\d{17}[0-9a-zA-Z]|\\d{14}[0-9a-zA-Z])");
// 用于提取出生日字符串的正則表達(dá)式
Patternpattern1 = Pattern.compile("\\d{6}(\\d{8}).*");
// 用于將生日字符串分解為年月日的正則表達(dá)式
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());
// 如果它是一個(gè)合法的身份證號(hào),提取出出生的年月日
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("它對(duì)應(yīng)的出生年月日為:" + matcher2.group(1) + "年" + matcher2.group(2) + "月"
+matcher2.group(3) + "日");
}
}
System.out.println();
}
}
}

到此這篇關(guān)于Java Pattern與Matcher字符串匹配案例詳解的文章就介紹到這了,更多相關(guān)Java Pattern與Matcher字符串匹配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問題
這篇文章主要介紹了關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
詳解Java多線程編程中LockSupport類的線程阻塞用法
LockSupport類提供了park()和unpark()兩個(gè)方法來實(shí)現(xiàn)線程的阻塞和喚醒,下面我們就來詳解Java多線程編程中LockSupport類的線程阻塞用法:2016-07-07
Spring Security 自定義短信登錄認(rèn)證的實(shí)現(xiàn)
這篇文章主要介紹了Spring Security 自定義短信登錄認(rèn)證的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析
這篇文章主要介紹了基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Java中十六進(jìn)制和十進(jìn)制之間互相轉(zhuǎn)換代碼示例
這篇文章主要給大家介紹了關(guān)于Java中十六進(jìn)制和十進(jìn)制之間互相轉(zhuǎn)換的相關(guān)資料,我們項(xiàng)目過程中總是要用到十進(jìn)制與十六進(jìn)制相互轉(zhuǎn)換的方法,需要的朋友可以參考下2023-07-07

