1. 程式人生 > 實用技巧 >Java正則表示式

Java正則表示式

如何匹配字串?

如何判斷字串是否是有效的電話號碼?

如何判斷字串是否是有效的電子郵件地址?

如何判斷字串是有效的時間?

從網頁上爬取資料後如何判斷哪些是圖片資源?

那我們就開始學習正則表示式吧!

正則表示式可以用字串來描述規則,並用來匹配字串

  • 一個正則表示式就是一個描述規則的字串
  • 只需要編寫正確的規則,就可以讓正則表示式引擎去判斷目標字串是否符合規則
  • 正則表示式是一套標準,可以用於任何語言
  • 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