[] 可接受的字符列表登馒,例如[abcd]表示匹配a瓮顽、b、c、d中任意一字符
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RexDemo {
public static void main(String[] args) {
String regExp = "[ab]";
String content = "apple and book";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
}
}
輸出
a
a
b
[^] 不可接受的字符列表 [^abc] 除a,b,c之外的任意一個(gè)字符蛔琅,包括數(shù)字和特殊符號近哟;
[^a-z]表示不匹配a-z中的任意一個(gè)字符溜腐;
[^0-9]表示不匹配0至9中任意一個(gè)字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RexDemo {
public static void main(String[] args) {
String regExp = "[^ab]";
String content = "a & b";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
}
}
輸出(注意空格符也被匹配上了):
' '
&
' '
[^a-z]{2} {2}表示連續(xù)2個(gè)字符不是a-z的字符棉钧,如A111匹配結(jié)果11
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RexDemo {
public static void main(String[] args) {
String regExp = "[^a-z]{2}";
String content = "a000b";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
}
}
輸出(匹配的是b前面的兩個(gè)00):
00
符號 - 符號 - 連字符 A-Z 任意單個(gè)大寫字母
符號. 匹配除\n以外的任何字符 a..b表示以a開頭屿脐,以b結(jié)尾,中間包括2個(gè)任意字符長度為4的字符串宪卿,如aaab,aefb,a35b,a*&b
\\d 匹配單個(gè)數(shù)字字符的诵,相當(dāng)于[0-9]
\\d{3} 等價(jià)與\\d\\d\\d
\\d{3}(\\d)? 包含3個(gè)或4個(gè)數(shù)字的字符串,如123愧捕,8765等
\\D 匹配單個(gè)非數(shù)字字符奢驯,相當(dāng)于[^0-9]
\\D(\\d)* 表示以單個(gè)非數(shù)字字符開頭申钩,后接任意個(gè)數(shù)字字符串次绘,如f、d1234等
\\w 匹配單個(gè)數(shù)字,大小寫字母邮偎,下劃線管跺,相當(dāng)于[0-9a-zA-Z_]
\\d{3}\\w{4} 表示以3個(gè)數(shù)字字符開頭的長度為7的字符串
\\W 匹配單個(gè)非數(shù)字、大消息字母字符禾进,相當(dāng)于[^0-9a-zA-Z_]
\\W+\\d{2} 表示匹配至少一個(gè)非數(shù)字豁跑,非字母字符開頭,2個(gè)數(shù)字字符結(jié)尾的字符串 如#26,#?@67
選擇匹配符號| 泻云,表示匹配"|"之前或之后的表達(dá)式艇拍,如 ab|cd 表示匹配ab或者cd
符號* 表示指定字符重復(fù)0次或者n次,如(abc)* 宠纯,僅包含任意個(gè)abc的字符串卸夕,等效與\W*,匹配abc婆瓜、abcabcabc
符號+ 表示指定字符重復(fù)1次或n次(至少一次)快集,m+(abc)*,以至少1個(gè)m開頭廉白,后接任意個(gè)abc的字符串个初,m,mabc猴蹂,mabcabc
(?i)abc 表示不區(qū)分大小寫院溺,匹配abc、Abc等
a(?i)bc或者a(?i)(bc) 表示bc不區(qū)分大消息
也可以手動(dòng)指定不區(qū)分大小寫
Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);
\\s 匹配任何空白字符(空格磅轻,制表符等)
\\S 匹配任何非空白字符覆获,和\s剛好相反
.匹配出\n之外的所有字符,如果要匹配.本身瓢省,則需要使用\\.
限定符 *+?{}
* 指定的字符重復(fù)0次或n次弄息,即0到多;如(abc)匹配abc,abcabc等
+ 指定字符重復(fù)1次或n次勤婚,如a+(bcd)*匹配至少1個(gè)a開頭摹量,任一個(gè)bcd結(jié)尾的字符,如a,abcd,abcdbcd等
?指定字符重復(fù)0或1次馒胆,如a+bc?表示至少一個(gè)a開頭缨称,b或者bc結(jié)尾的字符串,如ab或者abc祝迂,aabc等
{n}只能輸入n個(gè)字符睦尽,如[abcd]{3},表示由a,b,c,d中字母組成的任意長度為3的字符串型雳,如abc当凡,acd,adc等
{n,}至少n次匹配山害,[abcd]{3,}表示由abcd中字母組成的任意長度不小于3的字符串,如abc沿量,aab等
{n,m}指定至少n個(gè)但不多余m個(gè)匹配,[abcd]{3,5}表示由abcd中字母組成的任意長度在3到5之間的字符串浪慌,如abc,adddd等朴则;
定位符"^" "$" "\b" "\B"
^指定起始字符权纤,如^[0-9]+[a-z]*表示至少一個(gè)數(shù)字開頭,任意個(gè)小寫字母結(jié)尾的字符串乌妒,如9a,8等汹想;
$指定結(jié)束字符,^[0-9]\\-[a-z]$表示以一個(gè)數(shù)字開頭撤蚊,后接-欧宜,并以a到z任意一個(gè)字母結(jié)尾
^[0-9]\\-[a-z]+$表示以一個(gè)數(shù)字開頭,后接-拴魄,并以a到z任意一個(gè)或多個(gè)字母結(jié)尾
\\b 匹配目標(biāo)字符串的邊界冗茸,邊界指存在空格或者結(jié)尾,如aa\\b匹配kkkaa,kkaa匹中,kk aa等
\\B匹配目標(biāo)字符串的非邊界夏漱,邊界指開頭或者空格,如aa\\B顶捷,匹配aadkkklll挂绰,aa88,aa uu等
分組
1.非命名捕獲
(pattern) 非命名捕獲服赎,捕獲匹配的字符串葵蒂,編號為0的第一個(gè)捕獲是由整個(gè)正則表達(dá)式模式匹配的文本,其他捕獲結(jié)果則根據(jù)左括號的順序從1開始自動(dòng)編號
代碼實(shí)例
String content = "huawei nanjing2022 hua0318sheng";
String regExp = "(\\d\\d)(\\d\\d)";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
System.out.println(matcher.group(1));
System.out.println(matcher.group(2));
System.out.println("------");
}
輸出
2022
20
22
------
0318
03
18
------
2.命名捕獲
(?<name>pattern)命名捕獲重虑,將匹配的子字符串捕獲到一個(gè)組名稱或編號名稱中践付,用于name的字符串不能包含任何標(biāo)點(diǎn)符號,并且不能以數(shù)字開頭缺厉,可以使用單引號替代尖括號永高,如(?'name')
代碼實(shí)例
String content = "huawei nanjing2022 hua0318sheng";
String regExp = "(?<group1>\\d\\d)(?<group2>\\d\\d)";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
System.out.println(matcher.group(1));
System.out.println(matcher.group(2));
System.out.println(matcher.group("group1"));
System.out.println(matcher.group("group2"));
System.out.println("------");
}
輸出
2022
20
22
20
22
------
0318
03
18
03
18
------
3.非捕獲匹配(?:pattern)
表示匹配pattern,但不捕獲匹配的子表達(dá)式提针,對于用or字符"|"組合模式部件的情況很有用命爬,例如huaweinanjing|huaweishenzhen 比huawei(?:nanjing|shenzhen)要繁瑣
代碼實(shí)例
// String regExp = "huaweinanjing|huaweishenzhen|huaweihangzhou";
String regExp = "huawei(?:nanjing|shenzhen|hangzhou)";
String content = "hello huaweinanjing huaweishenzhen huaweihangzhou";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
運(yùn)行結(jié)果
huaweinanjing
huaweishenzhen
huaweihangzhou
4.非捕獲匹配(?=pattern)
(?=pattern)限定了捕獲的范圍,如tigger(?=3|5|7)匹配tigger3中的tigger辐脖,不匹配tigger2中的tigger
代碼實(shí)例
String regExp = "tigger(?=3|5|7)";
String content = "tigger2 tigger3 tigger5";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
輸出
tigger // tigger3中的tigger
tigger // tigger5中的tigger
5.非捕獲匹配(?!pattern)
該表達(dá)式匹配不處于匹配pattern的字符串的起始點(diǎn)的搜索字符串饲宛,如tigger(?!3|5|7)不匹配tigger3中tigger,不匹配tigger5中的tigger嗜价,不匹配tigger7中的tigger艇抠,但可以匹配tigger2中的tigger
代碼實(shí)例
String regExp = "tigger(?!3|5|7)";
String content = "tigger2 tigger3 tigger5";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
輸出
tigger // tigger2中的tigger
元字符說明
^幕庐、$、?(默認(rèn)非貪婪练链,如\\d+改成非貪婪匹配\\d+?只匹配一個(gè))
常用場景
1.校驗(yàn)字符串是否是漢字
// 校驗(yàn)字符串是否是漢字
String content = "華為";
String regExp = "^[\u0391-\uffe5]+$";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
System.out.println("是漢字");
} else {
System.out.println("不全部是漢字");
}
2.校驗(yàn)字符串是否是郵政編碼
// 校驗(yàn)字符串是否是郵政編碼
String content = "236566";
// 1-9開頭,緊接著是5位數(shù)字結(jié)尾
String regExp = "^[1-9]\\d{5}$";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
System.out.println("是");
} else {
System.out.println("否");
}
3.校驗(yàn)字符串是否是QQ號碼
// 校驗(yàn)字符串是否是QQ號碼
String content = "383754990";
// 1-9開頭翔脱,總長度在5到10位的數(shù)字
String regExp = "^[1-9]\\d{4,9}$";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
System.out.println("是");
} else {
System.out.println("否");
}
4.校驗(yàn)字符串是否是手機(jī)號碼
// 校驗(yàn)字符串是否是手機(jī)號碼
String content = "15276876755";
// 13奴拦,14媒鼓,15,18開頭的11位數(shù)字
String regExp = "^1[3|4|5|8]\\d{9}$";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
System.out.println("是");
} else {
System.out.println("否");
}
5.校驗(yàn)字符串是否是URL
String content = "https://www.bilibili.com/video/BV11A41157Sa?spm_id_from=333.999.0.0";
// 1. ^((http|https)://) 匹配https://
// 2. ([\w-]+\.)+[\w-]+ 匹配www.bilibili.com
// 3. (/[\w-?=&/%.#]*)? 匹配 /video/BV11A41157Sa?spm_id_from=333.999.0.0
// [\w-?=&/%.]匹配?错妖,=绿鸣,&,/暂氯,%潮模,.等
// [.]等價(jià)于//. 匹配.本身
// . 匹配除\n之外的所有字符
String regExp = "^((http|https)://)?([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
System.out.println("是");
} else {
System.out.println("否");
}
整體匹配
String content = "hello nanjing";
// String regExp = "hello"; // false
String regExp = "hello.* "; // true .*代表任意個(gè)字符
// 整體匹配
boolean matches = Pattern.matches(regExp, content);
System.out.println(matches);
注意事項(xiàng):整體匹配Pattern.matches()與matcher.find()存在一定區(qū)別,前者是整體匹配痴施,后者是局部匹配擎厢,正則表達(dá)式上存在一些區(qū)別,不能混用辣吃。
整體匹配與局部匹配區(qū)別的代碼實(shí)例
String content = "hello nanjing";
String regExp = "hello"; // false
// String regExp = "hello.* "; // true .*代表任意個(gè)字符
// 整體匹配
boolean matches = Pattern.matches(regExp, content);
System.out.println(matches);
System.out.println("---------------");
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(regExp);
if (matcher.find()) {
System.out.println("存在匹配的串");
} else {
System.out.println("不存在匹配的串");
}
輸出:
false
---------------
存在匹配的串
分組动遭、反向引用、捕獲
分組:用圓括號組成一個(gè)比較復(fù)雜的匹配模式神得,這個(gè)圓括號的部分可以看作是一個(gè)子表達(dá)式厘惦,也即一個(gè)分組
反向引用:圓括號的內(nèi)容被捕獲后,可以在這個(gè)括號后被使用哩簿,從而寫出一個(gè)比較實(shí)用的匹配模式宵蕉,這個(gè)我們稱為反向引用,這種引用既可以是在正則表達(dá)式的內(nèi)部节榜,也可以是在正則表達(dá)式的外部羡玛,內(nèi)部反向引用\分組號,外部反向引用$分組號
捕獲:把正則表達(dá)式中子表達(dá)式/分組匹配的內(nèi)容保存到內(nèi)存中以數(shù)字編號或顯式命名的組里宗苍,方便后面引用缝左,從左向右以分組的左括號為標(biāo)志,第一個(gè)出現(xiàn)的分組的組號為1浓若,第二個(gè)為2渺杉,以此類推,組0代表的是整個(gè)表達(dá)式
分組挪钓,反向引用是越,捕獲的代碼實(shí)例
String regExp = "(\\d)\\1"; // 表示連續(xù)兩位相同的數(shù)字,匹配如11碌上、44倚评、55等
String regExp = "(\\d)(\\d)\\2\\1"; // 表示連續(xù)的四位數(shù)字浦徊,1與4位相同,2與3位相同天梧,匹配如1221盔性、3223等
String regExp = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}"; // 匹配連續(xù)5位的數(shù)字,后面連-呢岗,后面連續(xù)9位數(shù)字冕香,其中每連續(xù)3位是相同的情況,如22221-777888999等
口吃去重實(shí)例:要求去掉一句話中連續(xù)重復(fù)的冗余字符后豫,只保留一個(gè)即可悉尾,如"我....我是中..中.國南南南京人",需要去掉“.”以及連續(xù)出現(xiàn)的字符挫酿,最終變成“我是中國南京人”
String content = "我....我是中..中.國南南南京人";
// 1.先去掉所有的.
String dotRegExp = "\\.";
Pattern pattern = Pattern.compile(dotRegExp);
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
// 2.去掉連續(xù)重復(fù)的字符构眯,只保留一個(gè)
// "(.)\\1+"表示匹配任意多個(gè)連續(xù)字符
// "$1"外部引用,使用第一個(gè)字符替換連續(xù)重復(fù)的字符
Pattern.compile("(.)\\1+").matcher((content)).replaceAll("$1");
String類中使用正則表達(dá)式
校驗(yàn)手機(jī)號是否138或者139開頭早龟,且長度11位
String content = "13887667805";
String regExp = "13(?:8|9)\\d{8}";
if (content.matches(regExp)) {
System.out.println("合法");
} else {
System.out.println("非法");
}
替換字符串中特定字符串
// 使用南京替換nanjing
String content = "nanjing1 是一座美麗的城市惫霸,nanjing2擁有悠久的歷史,豐厚的文化底蘊(yùn)...";
content = content.replaceAll("nanjing(?:1|2)", "南京");
System.out.println(content);
指定分割符分割字符串
// 分隔符為+葱弟、=壹店、*、-等符號
String content = "hell-o+nanjing=yuhua+998*77777";
String[] array = content.split("\\*|-|=|\\+");
for (String arr : array) {
System.out.println(arr);
}
常用場景
驗(yàn)證郵箱合法性
// .在中[]中表示.本身
// ^[\w-]+ 表示字符開頭翘悉,長度1到N位
// @ 表示@本身
// ([a-zA-Z0-9]+\\.)+ 表示1到N組"字母數(shù)字."的組合茫打,如cn.;com.妖混;edu.cn.等
// [a-zA-Z0-9]+ 表示字母數(shù)字組合長度1到N位不等
String regExp = "^[\\w-]+@([a-zA-Z0-9]+\\.)+[a-zA-Z0-9]+";
String content = "mac2099@163.com";
System.out.println(content.matches(regExp));
解析URL
注意:下面的代碼邏輯只具有一定的參考性老赤,具體解析規(guī)則要根據(jù)實(shí)際要求來定
String content = "https://www.bilibili.com/video/BV11A41157Sa?spm_id_from=333.999.0.0&name=zhangsan";
// 采用分組方式處理
String regExp = "([a-zA-Z]+)://([\\w-.]+)(:\\d+|)([/\\w-]*)([?]*)([[\\w_.]*=[\\w_.]*&*]+)";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println(matcher.group(0));
// 協(xié)議
System.out.println(matcher.group(1));
// 域名
System.out.println(matcher.group(2));
// 路徑
System.out.println(matcher.group(4));
// 參數(shù)列表
System.out.println(matcher.group(6));
}
常用正則表達(dá)式參考
數(shù)字 :^[0-9]*$
n位的數(shù)字:^\d{n}$
至少n位的數(shù)字:^\d{n,}$
m-n位的數(shù)字:^\d{m,n}$
零或者非零開頭的 數(shù)字:^(0|[1-9][1-9]*)$
非零開頭的最多帶兩位小數(shù)的數(shù)字:^([1-9][0-9*])+(.[0-9]{1-2})?$
帶1-2位小數(shù)的正數(shù)或負(fù)數(shù):^(\-)?\d+(\.\d{1,2})?$
正數(shù)、負(fù)數(shù)和小數(shù):^(\-|\+)?\d+(\.\d+)?$
兩位小數(shù)的正數(shù):^[0-9]+(.[0-9]{2})?$
有1-3位小數(shù)的正數(shù):^[0-9]+(.[0-9]{1,3})?$
非零的正整數(shù):^[1-9][0-9]*$或^[1-9]\d*$等
非零的負(fù)整數(shù):^-[1-9]\\d*$
非負(fù)整數(shù):^\\d+$或者^[1-9]\\d*|0$
非正整數(shù):^-[1-9]\\d*|0$或者^((-\\d+)|(0+))$
非負(fù)浮點(diǎn)數(shù):^\\d+(\\.\\d+)?$
非正浮點(diǎn)數(shù):^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$
正浮點(diǎn)數(shù):^[1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$
負(fù)浮點(diǎn)數(shù):^-([1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$
浮點(diǎn)數(shù):^(-?\\d+)(\\.\\d+)?$
校驗(yàn)字符表達(dá)式
漢字:^[\u4e00-\u9fa5]+$
英文和數(shù)字:^[A-Za-z0-9]+$
長度為3-20的所有字符:^.{3,20}$
中文制市,英文抬旺,數(shù)字包括下劃線:^[\u4e00-\u9fa5A-Za-z0-9_]+$
可以輸入含有^T%,;=?$\等字符:[^T%,;=?$\x22]+
禁止輸入含有~的字符[^~\x22]+