1、正則表達式:
1. 正則表達式其實就是一種規則,有自己特殊的應用,其作用就是針對字符串進行操作
2. 正則:就是用於操作字符串的一種規則,其中這些規則使用了一些字符表示
2、預定義字符類
. 點 表示任何字符(與行結束符可能匹配也可能不匹配)
\d 數字:[0-9]
\D 非數字: [^0-9]
\s 空白字符:[ \t \n \x0B \f \r]
\S 非空白字符:[^\s]
\w 單詞字符:[a-z A-Z _ 0-9]
\W 非單詞字符:[^\w]
注意:任何預定義字符在沒有加上數量詞之前,都只能匹配一個字符而已。
2.1 預定義字符案例
// . 表示任意字符,匹配任意字符都返回true
System.out.println(". 匹配任意字符?" + ("a".matches(".")));
System.out.println();
// \d 表示數字0-9其中一位,匹配0-9返回true,其他返回false
System.out.println("\\d 匹配任意數字[0-9]?" + ("3".matches("\\d")));
System.out.println();
// \D 表示非數字,即非\d [^0-9],只要不是數字0-9即返回true
System.out.println("\\D 匹配任意非數字字符:?" + ("a".matches("\\D")));
System.out.println();
// \s 表示空白字符 [ \t \n \x0B \f \r ],匹配這些空調字符返回true,其他返回false
System.out.println("\\s 匹配任意空白字符?" + ("\t".matches("\\s")));
System.out.println();
// \S 表示非空表字符 [^\s]
System.out.println("\\S 匹配任意非空白字符?" + ("s".matches("\\S")));
System.out.println();
// \w 表示單詞字符:[a-zA-Z_0-9],匹配大小寫a-z,數字0-9,下劃線_,返回true,其他返回false
System.out.println("\\w 匹配任意單詞字符?" + ("_".matches("\\w")));
System.out.println();
// \W 表示非單詞字符:[^\w]
System.out.println("\\W 匹配任意非單詞字符:?" + ("#".matches("\\W")));
執行結果:
. 匹配任意字符?true
\d 匹配任意數字:(匹配一位數字[0-9])?true
\D 匹配任意非數字字符:?true
\s 匹配任意空白字符?true
\S 匹配任意非空白字符?true
\w 匹配任意單詞字符?true
\W 匹配任意非單詞字符:?true
3、Greedy 數量詞
X ? 一次或一次也沒有(?表示 最多出現一次X字符) X * 零次或多次(* 表示 任意次) X + 一次或多次(+ 表示 最少出現一次X字符) X {n} 恰好n次(出現n次X字符) X {n,} 至少n次(最少出現n次X字符) X {n,m} 至少n次,最多m次(出現n<=x<=m 次X字符)
3.1 Greedy 數量詞案例:
// X ?: 問號 表示一次或一次也沒有(最多出現一次X字符)
System.out.println("? 表示 最多一次(0次)?" + ("".matches("\\w?")));// true
System.out.println("? 表示 最多一次(1次)?" + ("a".matches("\\w?")));// true
System.out.println("? 表示 最多一次(2次)?" + ("aa".matches("\\w?")));// false
System.out.println();
// X *: 星號 表示零次或多次(出現任意次數的X字符)
System.out.println("*表示出現 任意次(0次)?" + ("".matches("\\d*")));// true
System.out.println("*表示出現 任意次(1次)?" + ("1".matches("\\d*")));// true
System.out.println("*表示出現 任意次(2次)?" + ("11".matches("\\d*")));// true
System.out.println();
// X +: 加號表示一次或多次(最少出現一次)
System.out.println("+表示出現1次或多次(0次)?" + ("".matches("\\d+")));// false
System.out.println("+表示出現1次或多次(1次)?" + ("1".matches("\\d+")));// true
System.out.println("+表示出現1次或多次(2次)?" + ("11".matches("\\d+")));// true
System.out.println();
// X {n}: {n}大括號裏寫次數,表示正好出現n次X字符
System.out.println("{2} 表示恰好出現2次(1次)?" + "1".matches("\\d{2}"));// false
System.out.println("{2} 表示恰好出現2次(2次)?" + "11".matches("\\d{2}"));// true
System.out.println("{2} 表示恰好出現2次(3次)?" + "111".matches("\\d{2}"));// false
System.out.println();
// X {n,}: 表示至少出現n次X字符,n次或以上爲true,n次以下爲false
System.out.println("{2,} 表示恰好出現2次(1次)?" + "1".matches("\\d{2,}"));// false
System.out.println("{2,} 表示恰好出現2次(2次)?" + "11".matches("\\d{2,}"));// true
System.out.println("{2,} 表示恰好出現2次(3次)?" + "111".matches("\\d{2,}"));// true
System.out.println();
// X {n,m}: 表示最少出現n次,最多出現m次
System.out.println("{2,4} 表示至少出現2次,最多出現4次(1次)?" + ("1".matches("\\d{2,4}")));// false
System.out.println("{2,4} 表示至少出現2次,最多出現4次(2次)?" + ("11".matches("\\d{2,4}")));// true
System.out.println("{2,4} 表示至少出現2次,最多出現4次(3次)?" + ("122".matches("\\d{2,4}")));// true
System.out.println("{2,4} 表示至少出現2次,最多出現4次(4次)?" + ("1333".matches("\\d{2,4}")));// true
System.out.println("{2,4} 表示至少出現2次,最多出現4次(5次)?" + ("14444".matches("\\d{2,4}")));// false
System.out.println();
執行結果:
? 表示 最多一次(0次)?true
? 表示 最多一次(1次)?true
? 表示 最多一次(2次)?false
* 表示出現 任意次(0次)?true
* 表示出現 任意次(1次)?true
* 表示出現 任意次(2次)?true
+ 表示出現1次或多次(0次)?false
+ 表示出現1次或多次(1次)?true
+ 表示出現1次或多次(2次)?true
{2} 表示恰好出現2次(1次)?false
{2} 表示恰好出現2次(2次)?true
{2} 表示恰好出現2次(3次)?false
{2,} 表示恰好出現2次(1次)?false
{2,} 表示恰好出現2次(2次)?true
{2,} 表示恰好出現2次(3次)?true
{2,4} 表示至少出現2次,最多出現4次(1次)?false
{2,4} 表示至少出現2次,最多出現4次(2次)?true
{2,4} 表示至少出現2次,最多出現4次(3次)?true
{2,4} 表示至少出現2次,最多出現4次(4次)?true
{2,4} 表示至少出現2次,最多出現4次(5次)?false
4、範圍表示
[abc]: 表示 a、b 或 c [^abc]: 表示 任何字符,除了 a、b 或 c [a-zA-Z]: 表示 a-z 或 A-Z,兩頭的字母包括在內 [a-d[m-p]]: 表示 a-d 或者 m-p 的並集 [bcd&&[def]]: 表示bcd與def的交集 [a-z&&[^bc]]: 表示 a-z,除了 b 和 c:[a或者d-z] [a-z&&[^m-p]]: 表示 a-z和 【a-z 除去m-p】的交集,即 a-l 或者 q-z
4.1 範圍表示 案例
// [abc]:表示匹配a、b 或 c其中的一個字符(簡單類)
System.out.println("[abc]表示匹配a或b或c爲true(a)?" + ("a".matches("[abc]")));//true
System.out.println("[abc]表示匹配a或b或c爲true(e)?" + ("e".matches("[abc]")));//false
System.out.println();
// [^abc]:表示匹配任何字符(1個),除了 a、b 或 c(否定)
System.out.println("[^abc]表示匹配除abc之外的任意一個字符(a)?" +
("a".matches("[^abc]")));//false
System.out.println("[^abc]表示匹配除abc之外的任意一個字符(3)?" +
("3".matches("[^abc]")));//true
System.out.println();
//[a-zA-Z]:表示匹配 a到z 或 A到Z 中的任意一個字符,兩頭的字母包括在內(範圍)
System.out.println("[a-zA-Z]表示匹配a-z和A-Z之中的任意一個字符(F)?" + ("F".matches("[a-zA-Z]")));//true
System.out.println("[a-zA-Z]表示匹配a-z和A-Z之中的任意一個字符(f)?" + ("f".matches("[a-zA-Z]")));//true
System.out.println("[a-zA-Z]表示匹配a-z和A-Z之中的任意一個字符(3)?" + ("3".matches("[a-zA-Z]")));//false
System.out.println();
//[a-d[m-p]]:表示 a到d 或 m到p中的任意一個字符(並集)
System.out.println("[a-d[m-p]]表示匹配a-d或m-p之中的任意一個字符(B)?" + ("B".matches("[a-d[m-p]]")));//false
System.out.println("[a-d[m-p]]表示匹配a-d或m-p之中的任意一個字符(b)?" + ("b".matches("[a-d[m-p]]")));//true
System.out.println("[a-d[m-p]]表示匹配a-d或m-p之中的任意一個字符(m)?" + ("m".matches("[a-d[m-p]]")));//true
System.out.println();
// [bcd&&[def]]: 表示bcd和def的交集,結果是字符d
System.out.println("[bcd&&[def]]表示abcd和def的交集(即d)(d)?" +
("d".matches("[bcd&&[def]]")));// true
System.out.println("[bcd&&[def]]表示abcd和def的交集(即d)(e)?" +
("e".matches("[bcd&&[def]]")));// false
System.out.println("[bcd&&[def]]表示abcd和def的交集(即d)(f)?" +
("f".matches("[bcd&&[def]]")));// false
System.out.println();
// [a-z&&[^bc]] 表示a到z 和 【a-z除了b和c】的交集,結果是a或d-z中的一個字符
System.out.println("[a-z&&[^bc]]表示a到z 和 【a-z除了b和c】的交集(a)?" + "a".matches("[a-z&&[^bc]]"));// true
System.out.println("[a-z&&[^bc]]表示a到z 和 【a-z除了b和c】的交集(b)?" + "b".matches("[a-z&&[^bc]]"));// false
System.out.println("[a-z&&[^bc]]表示a到z 和 【a-z除了b和c】的交集(z)?" + "z".matches("[a-z&&[^bc]]"));// true
System.out.println();
// [a-z&&[^m-p]]:表示 a-z 與【a-z減去m-p】的交集,結果是a-l和q-z中的一個字符
System.out.println("[a-z&&[^m-p]]表示 a-z 與【a-z減去m-p】的交集(a)?" + "a".matches("[a-z&&[^m-p]]"));// true
System.out.println("[a-z&&[^m-p]]表示 a-z 與【a-z減去m-p】的交集(m)?" + "m".matches("[a-z&&[^m-p]]"));// false
System.out.println("[a-z&&[^m-p]]表示 a-z 與【a-z減去m-p】的交集(z)?" + "z".matches("[a-z&&[^m-p]]"));// true
System.out.println();
執行結果:
[abc]表示匹配a或b或c爲true(a)?true
[abc]表示匹配a或b或c爲true(e)?false
[^abc]表示匹配除abc之外的任意一個字符(a)?false
[^abc]表示匹配除abc之外的任意一個字符(3)?true
[a-zA-Z]表示匹配a-z和A-Z之中的任意一個字符(F)?true
[a-zA-Z]表示匹配a-z和A-Z之中的任意一個字符(f)?true
[a-zA-Z]表示匹配a-z和A-Z之中的任意一個字符(3)?false
[a-d[m-p]]表示匹配a-d或m-p之中的任意一個字符(B)?false
[a-d[m-p]]表示匹配a-d或m-p之中的任意一個字符(b)?true
[a-d[m-p]]表示匹配a-d或m-p之中的任意一個字符(m)?true
[bcd&&[def]]表示abcd和def的交集(即d)(d)?true
[bcd&&[def]]表示abcd和def的交集(即d)(e)?false
[bcd&&[def]]表示abcd和def的交集(即d)(f)?false
[a-z&&[^bc]]表示a到z 和 【a-z除了b和c】的交集(a)?true
[a-z&&[^bc]]表示a到z 和 【a-z除了b和c】的交集(b)?false
[a-z&&[^bc]]表示a到z 和 【a-z除了b和c】的交集(z)?true
[a-z&&[^m-p]]表示 a-z 與【a-z減去m-p】的交集(a)?true
[a-z&&[^m-p]]表示 a-z 與【a-z減去m-p】的交集(m)?false
[a-z&&[^m-p]]表示 a-z 與【a-z減去m-p】的交集(z)?true
注意:正則表達式中 大括號{ n }表示次數,中括號[a-z]表示範圍。
注意:範圍詞裏邊,不管內容有多長,沒有數量詞的配合,只能匹配其中的一個字符。
5、分組()
爲了提高規則的複用,用()小括號來對正則表達式的字節進行分組,每個括號都有一個編號,編號從1開始。可以通過編號來完成對該規則的調用。注意:需要對編號規則進行轉義,\\1就表示獲取第一組規則,\\2代表獲取第二組規則,以此類推。
5.1 案例
// 需求:將手機號的中間四位使用*號代替
// 第一步,找到手機號,將手機號分組成三部分,前三位是第一組,中間四位是第二組,最後四位是第三組
// 第二步,將手機號的中間4位用 * 號代替
public static void testReplace() {
String str = "聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119";
// 使用小括號將正則表達式分爲3組。
String reg = "(1[34578][0-9])(\\d{4})(\\d{4})";
// // $1表示匹配到的第1組子表達式,$3表示第三組子表達式。$1,$2,$3這種格式直接寫在正則表達式中是錯誤的,它只是起到一個佔位的作用。
String s = str.replaceAll(reg, "$1****$3");
System.out.println("替換後的帖子是:" + s);
}
執行結果:
替換後的帖子是:聯繫我:135****2119聯繫我:135****2119聯繫我:135****2119聯繫我:135****2119聯繫我:135****2119聯繫我:135****2119
6.邊界匹配器
^ | 行的開頭 |
$ | 行的結尾 |
\b | 單詞邊界 |
\B | 非單詞邊界 |
\A | 輸入的開頭 |
\G | 上一個匹配的結尾 |
\Z | 輸入的結尾,僅用於最後的結束符(如果有的話) |
\z | 輸入的結尾 |
7.正則表達式的四種常見應用
1. 匹配
常用方法 matches(reg)
2. 切割
常用方法 split(reg)
3. 替換
常用方法 replace(reg,replacement) 、replaceAll(reg,replaement)
4. 查找
此時需要使用正則表達式對象
7.1 正則表達式的常見應用案例:
public static void main(String[] args) {
// 1.匹配應用
System.out.println("使用正則表達式匹配手機號:" + matchesPhone("13933395149"));
System.out.println("使用正則表達式匹配固話:" + matchesTel("0315-7421005"));
System.out.println();
// 切割應用
System.out.println("使用正則表達式按照空格進行切割:" + Arrays.toString(testSplit1(" 今 天 大 家 玩 的 開 心 ")));
System.out.println("使用正則表達式按照重疊詞進行切割:" + Arrays.toString(testSplit2("大家家家家家玩玩的的的的開心心心!!!")));
// 替換應用
testReplace1();
testReplace2();
// 查找應用
getWord();;
}
// 需求:正則表達式匹配手機號,第一位是1,第二位345789,後邊全是數字,一共11位
public static String matchesPhone(String phone) {
String reg = "1[34578]\\d{9}";
return phone.matches(reg) ? "合法手機號" : "非法手機號";
}
// 需求:正則表達式匹配固話 區號首位是0,長度3-4位,主機號,首位不能是0,長度7-8位
public static String matchesTel(String tel) {
String reg = "0\\d{2,3}-[1-9]\\d{6,7}";
return tel.matches(reg) ? "合法固話" : "非法固話";
}
// 按照空格進行切割
public static String[] testSplit1(String string) {
return string.split(" +");
}
// 根據重疊詞進行切割
public static String[] testSplit2(String string) {
// 如果正則的內容需要被複用,那麼需要對正則的內容進行分組,分組的目的是 爲了提高正則的複用性。
return string.split("(.)\\1+(.)\\2+");
}
// 需求:將字符串中的手機號中間4位替換成****號
public static void testReplace1() {
String str = "聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119聯繫我:13567012119";
String reg = "(1[34578][0-9])(\\d{4})(\\d{4})";
// $1表示匹配到的第1組子表達式,$3表示第三組子表達式。$1,$2,$3這種格式直接寫在正則表達式中是錯誤的,它只是起到一個佔位的作用
String s = str.replaceAll(reg, "$1****$3");
System.out.println("替換後的帖子是:" + s);
}
// 需求:"我我....我...我.要...要要...要學....學學..學.編..編編.編.程.程.程..程",將字符串還原成 "我要學編程"。
// 分析:第一步:先將所有點去掉。 第二步將所有重疊字進行切割並保留一個
public static void testReplace2() {
String str = "我我....我...我.要...要要...要學....學學..學.編..編編.編.程.程.程..程";
// 將所有.去掉
str = str.replaceAll("\\.+", "");
System.out.println(str);
// 將重疊字進行疊詞處理,並保留一個
str = str.replaceAll("(.)\\1+", "$1");
System.out.println(str);
}
8、通用的正則表達式
手機號: ^1(3[\\d]|4[579]|5[0-3[5-9]]|6[2[5-7]]|7[1-3[5-8]]|8[0-9]|9[0-3[5-9]])\\d{8}$
郵箱: ^[0-9a-zA-Z]+([-\\w])+@([\\w]+\\.)+[a-z]{2,}$
或
^[a-z0-9A-Z]+[-|a-z0-9A-Z._]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-z]{2,}$
手機號和郵箱的通用表達式有多重寫法,可以根據自己的習慣編寫,比如將 [0-9] 寫成 [\\d],或者將 [0-3[5-9]] 寫成 [0-9&&[^4]],找到規律就好。勤加練習,應付工作上的一般狀況還是很輕鬆的。
9、正則對象
1、查找需要使用的對象:
Pattern:正則對象
Matcher:匹配器
2、正則表達式的編譯表示形式。
指定爲字符串的正則表達式必須首先被編譯爲此類的實例。然後,可將得到的模式用於創建 Matcher 對象,
依照正則表達式,該對象可以與任意字符序列匹配。執行匹配所涉及的所有狀態都駐留在匹配器中,所以多個匹配器可以共享同一模式。
因此,典型的調用順序是
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
3、匹配器要使用的方法
find():通知匹配器去匹配字符串,查找符合規則的子串。如果能查找到符合規則的子字符串,返回true,否則返回false
group():獲取符合規則的子串
注意:使用group方法之前,一定要使用find方法去查找符合規則的字符串,否則報錯。
9.1 案例
使用正則對象查找符合正則表達式規則的內容:需求 在字符串中查找由三個字母組成的單詞
// 需求:在字符串中獲取由三個字母組成的單詞
public static void getWord() {
String str = "da jia hao , ming tian bu fang jia , xie xie !";
String reg = "\\b[a-zA-Z]{3}\\b";
// 首先要把字符串的正則編譯成Pattern正則對象,\b表示單詞的邊界
Pattern pattern = Pattern.compile(reg);
// 使用正則對象匹配字符串,用於產生一個Matcher 匹配器對象
Matcher matcher = pattern.matcher(str);
// matcher.find():判斷字符串中是否存在符合正則表達式的內容
// matcher.group():獲取符合正則規則的字符串內容
while (matcher.find()) {
System.out.println(matcher.group());
}
}