如何匹配字符串?
如何判斷字符串是否是有效的電話號碼?
如何判斷字符串是否是有效的電子郵件地址?
如何判斷字符串是有效的時間?
從網頁上爬取數據后如何判斷哪些是圖片資源?
那我們就開始學習正則表達式吧!
正則表達式可以用字符串來描述規則,並用來匹配字符串
- 一個正則表達式就是一個描述規則的字符串
- 只需要編寫正確的規則,就可以讓正則表達式引擎去判斷目標字符串是否符合規則
- 正則表達式是一套標准,可以用於任何語言
- JDK內置正則表達式引擎:java.util.regex
我們來舉個例子:判斷用戶輸入的年份是否是19xx年
首先用戶輸入的規則是:
然后我們就可以編寫出相應的正則表達式:1 9 \d \d (\d表示0-9的任意一個數字)
所有對應的Java字符串: "19\\d\\d" (java中\是轉移字符所有我們要用兩個反斜杠來表示一個反斜杠)
Java代碼:
String input = "1996";
boolean matches = input.matches("19\\d\\d");
if (matches){
System.out.println("輸入格式正確");
}else {
System.out.println("輸入格式錯誤");
}
正則表達式的匹配規則
- 從左到右按規則匹配
如何編寫正則表達式?
1、精確匹配:"abc"
表示精確的匹配"abc"這個字符串,並且大小寫敏感,不能匹配"Abc"
String input = "abcd";
boolean matches = input.matches("abc");
if (matches){
System.out.println("輸入格式正確");
}else {
System.out.println("輸入格式錯誤");
}
//輸入格式錯誤
//如果 String input = "abc"; 則輸入格式正確
2、精確匹配:"a\&c",特殊字符需要轉義
3、特殊符號 . 可以匹配一個任意字符 : "a.c"
String input = "a和c";
boolean matches = input.matches("a.c");
if (matches){
System.out.println("輸入格式正確");
}else {
System.out.println("輸入格式錯誤");
}
}
//格式正確
//”ac“ 和 "abbc" 是不會匹配成功的
4、符號\d可以匹配一個數字:"00\d"
String input = "009";
boolean matches = input.matches("00\\d");
//"009" 匹配成功
//"00A"和"0088"是不會匹配成功的
5、符號\w可以匹配一個字母、數字或下划線: "java\w"
String input = "java_";
boolean matches = input.matches("java\\w");
//"java_" 匹配成功
//"java#" 和 "java "是不會匹配成功的
6、符號\s可以匹配一個空白字符 : "A\sB"
String input = "A B";
boolean matches = input.matches("A\\sB");
// B"匹配成功
// B" 可以匹配成功 tab鍵也算空白字符
//B" 和 "A B" 不行
7、符號\D可以匹配一個非數字: "00\D"
String input = "00A";
boolean matches = input.matches("00\\D");
//"00A" 匹配成功
//"001" 和 "004" 不行
8、符號\W可以匹配一個非字母、數字或下划線: "java\W"
String input = "java!";
boolean matches = input.matches("java\\W");
//"java!" 匹配成功
//"java2" 、 "Javaa" 和 "java_" 不行
9、符號\S可以匹配一個非空白字符
String input = "ABB";
boolean matches = input.matches("A\\SB");
//"A&B" 也可以成功
//"A B" 和 "A B" 不行 tab鍵也算空白鍵
10、修飾符*可以匹配任意個字符: "A\d*"
String input = "A4674";
boolean matches = input.matches("A\\d*");
// "A" , "A1" 和 "A876" 都可以
// "AH" 不行
11、修飾符+可以匹配至少一個字符:"A\d+"
String input = "A4674";
boolean matches = input.matches("A\\d+");
//"A4674"
//"A" 、 "AV" 不可以
12、修飾符?可以匹配零個或者一個字符: "A\d?"
String input = "A4";
boolean matches = input.matches("A\\d?");
// "A" "A1" 可以
// "A12" "Ab" 不可以
13、修飾符{n}可以匹配n個字符: "\d{6}"
String input = "345325";
boolean matches = input.matches("\\d{6}");
//"123456" "111111" 可以
//"1234" "12345a" 不行
14、修飾符{n,m}可以匹配n-m個字符:"\d{3,5}"
String input = "34532";
boolean matches = input.matches("\\d{3,5}");
//"123" "12345" 可以
//"123456" "1234A" 不行
15、修飾符{n,}可以匹配至少n個字符:"\d{3,}"
String input = "123";
boolean matches = input.matches("\\d{3,}");
//"123" "12345" "1234567" 可以
//"12" "12A" 不行
我們給簡單匹配規則做個小總結
正則表達式 | 規則 | 可以匹配 |
---|---|---|
A | 指定字符 | A |
. | 任意字符 | a,c,d,&,4 |
\d | 0-9 | 0,1,2,3.....9 |
\w | a-z,A-Z,1-9,_ | a,A,2,_...... |
\s | 空格,Tab鍵 | " " |
\D | 非數字 | a,A,&,_...... |
\W | 非\w | &^%$... |
\S | 非\s | a,A,%,_ |
我們再來看看復雜一點的匹配規則
1、和$匹配開始和結尾:"A\d{3}$"
String input = "A001";
boolean matches = input.matches("^A\\d{3}$");
//"A001" "A777" 可以
//"B001" "B0001" 不行
2、[...]可以匹配范圍內的字符:"[abc]1" 只能匹配某一個字符
String input = "A001";
boolean matches = input.matches("[abc]1");
//"a1" "b1" "c1" 可以
//"ab1" "x1" 不行
3、[...] 可以匹配范圍內的字符:"[a-f]1"
String input = "d1";
boolean matches = input.matches("[a-f]1");
//"a1" "b1" "f1"可以
//"r1" "ab1" 不行
4、[...] 可以匹配范圍內的字符:"[a-f0-9]{6}}"
String input = "433abc";
boolean matches = input.matches("[a-f0-9]{6}");
//"1a2b4c" "ffffff" "111111" 可以
//"agc2" "ad222F" 不行 F大寫不在a-f范圍內
//還可以寫成 boolean matches = input.matches("[a-f0-9_]{6}");
//那就還可以匹配_
5、[^] 可以匹配非范圍內的字符:"[ ^ 0-9]"
String input = "asdfgh";
boolean matches = input.matches("[^0-9]{6}");
//"asdfgh" "$$$$$$" "a-b-c" 可以
//"123456" "ads23f" 不可以
6、AB|CD 可以匹配AB或CD : "java|go"
String input = "java";
boolean matches = input.matches("java|go");
//"java" "go" 可以
//"c++" "javago" 不行
//再舉個例子
boolean matches = input.matches("love\\s(java|go)");
//"love java" "love go" 可以
//"love c++" "love python" 不可以
我們來做個小總結
正則表達式 | 規則 | 可以匹配 |
---|---|---|
^ | 開頭 | 字符串開頭 |
$ | 結尾 | 字符串結尾 |
[ABC] | [...]內任意字符 | A,B,C |
[a-f0-9xy] | 指定范圍的字符 | a,2,x,y |
[^A-F] | 指定范圍外的任意字符 | 非A....F |
AB|CD | AB或CD | AB,CD |
AB|CD|EF | AB或CD或EF | AB,CD,EF |
再來說一說分組匹配規則
1、(...)可以分組:(\d{4}\-\d{1,2}\-(\d{1,2}))
String input = "2020-11-22";
boolean matches = input.matches("(\\d{4}\\-(\\d{1,2})\\-(\\d{1,2}))");
//"2020-11-22" 可以
我們再來舉個例子,提取電話號碼
-########
^ \d{3,4} \- \d{6,8} $
^ :開頭
\d{3,4}:3-4位區號
\- : 符號"-"
\d{6,8}:6-8位電話號碼
$ 結束
String input = "010-1234567";
boolean matches = input.matches("^(\\d{3,4})\\-(\\d{6,8})$");
//"010-1234567"可以
反復使用一個正則表達式字符串進行快速匹配效率較低(方法內部實際上是調用了Pattern對象)
我們可以把正則表達式編譯為Pattern對象,然后反復使用他,就可以實現一次編譯多次匹配
Pattern pattern = Pattern.compile("^(\\d{3,4})\\-(\\d{6,8})$");
boolean matches = pattern.matcher("010-1234567").matches();
if (matches){
System.out.println("輸入格式正確");
}else {
System.out.println("輸入格式錯誤");
}
**使用Matcher.group(n)可以快速提取子串 ** 一個()代表一個子串
Pattern pattern = Pattern.compile("^(\\d{3,4})\\-(\\d{6,8})$");
Matcher matcher = pattern.matcher("010-1234567");
if (matcher.matches()){
String whole = matcher.group(0); //"010-1234567" 0表示匹配整個字符串
String areaCode = matcher.group(1); //"010" ,1表示匹配第一個字符串
String telNumber = matcher.group(2); //"1234567",表示匹配的第二個字符串
}
非貪婪匹配
正則表達式默認使用貪婪匹配
- 盡可能多的向后匹配
- 使用?實現非貪婪匹配
搜索和替換
使用正則表達式分割字符串
-
String[] String.split(String regex)
String[] split = "a b c".split("\\s");//["a", "b", "c"] String[] split = "a b c".split("\\s");//["a", "b","", "c"] String[] split = "a b c".split("\\s+");//["a", "b","c"] String[] split = "a, b;; c".split("\\,\\;\\s+");//["a", "b","c"]
使用正則表達式搜索字符串
- Matcher.find()
String str = "I love you";
Pattern pattern = Pattern.compile("love");
Matcher matcher = pattern.matcher(str);
while (matcher.find()){
String substring = str.substring(matcher.start(), matcher.end());
System.out.println(substring);
}
使用正則表達式替換字符串
-
String.replaceAll()
String str = "I love you"; String all = str.replaceAll("\\s+", ""); //Iloveyou