首頁 > 軟體

一文搞懂正規表示式基礎語法以及如何應用

2022-09-30 14:00:55

一、正規表示式

1、基本介紹

▶ 概述

  1. 一個正規表示式,就是用某種模式去匹配字串的一個公式。很多人因為它們看上去比較古怪而且複雜所以不敢去使用,不過,經過練習後就覺得這些複雜的表示式寫起來還是相當簡單的, 而且, 一旦你弄懂它們,你就能把數小時辛苦而且易錯的文書處理工作縮短在幾分鐘(甚至幾秒鐘)內完成。
  2. 正規表示式不是隻有java才有,實際上很多程式語言都支援正規表示式進行字串操作!

▶ 快速入門

public class RegTheory {
    public static void main(String[] args) {
        //目標:匹配所有四個數位
        String content = "2002fsd ke ire i2222 ";
 
        //1. \d 表示一個任意的數位
        String regStr = "(\d\d)(\d\d)";
 
        //2. 建立模式物件[即正規表示式物件]
        Pattern pattern = Pattern.compile(regStr);
 
        //3. 建立匹配器
        //說明:建立匹配器 matcher, 按照 正規表示式的規則 去匹配 content 字串
        Matcher matcher = pattern.matcher(content);
 
        //4. 開始匹配
        while (matcher.find()) {
            System.out.println("找到: " + matcher.group(0));
            System.out.println("第 1 組()匹配到的值=" + matcher.group(1));
            System.out.println("第 2 組()匹配到的值=" + matcher.group(2));
        }
    }
}

▶ 底層原始碼

        matcher.find() 完成的任務 (考慮分組),{什麼是分組,比如 (dd)(dd) ,正規表示式中有() 表示分組,第 1 個()表示第 1 組,第 2 個()表示第 2 組...}
        1. 根據指定的規則 , 定位滿足規則的子字串 ( 比如 (20)(02))
        2. 找到後,將 子字串的開始的索引記錄到 matcher 物件的屬性 int[ ] groups;
         ▷ groups[0] = 0 , 把該子字串的結束的索引+1 的值記錄到 groups[1] = 4
         ▷ 記錄 1 組 () 匹配到的字串 groups[2] = 0 groups[3] = 2
         ▷ 記錄 2 組 () 匹配到的字串 groups[4] = 2 groups[5] = 4
         ▷ 如果有更多的分組.....
        3. 同時記錄 oldLast 的值為 子字串的結束的 索引 +1 的值即 16, 即下次執行 find 時,就從 16  開始匹配。

▶ matcher.group(0) 分析

public String group(int group) {
    if (first < 0){
        throw new IllegalStateException("No match found");
    }
 
    if (group < 0 || group > groupCount()){
        throw new IndexOutOfBoundsException("No group " + group);
    }
 
    if ((groups[group*2] == -1) || (groups[group*2+1] == -1)){
        return null;
    }
 
    return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}

根據 groups[0]=16 和 groups[1]=20  的記錄的位置,從 content 開始擷取子字串返回

就是 [16,20) 包含 16  但是不包含索引為 20  的位置  如果再次指向 find 方法 . 仍然安上面分析來執行。

▶ 小結

        1. 如果正規表示式有() 即分組
        2. 取出匹配的字串規則如下
        3. group(0) 表示匹配到的子字串
        4. group(1) 表示匹配到的子字串的第一組字串
        5. group(2) 表示匹配到的子字串的第 2 組字串
        6. ... 但是分組的數不能越界.

2、正規表示式語法

▶ 基本介紹

     如果要想靈活的運用正規表示式,必須瞭解其中各種元字元的功能,元字元從功能上大致分為:

     ①限定符,②選擇匹配符,③分組組合和反向參照符,④特殊字元,⑤字元匹配符,⑥定位符

▶ 元字元(Metacharacter)-跳脫號

        符號說明: 在我們使用正規表示式去檢索某些特殊字元的時候,需要用到跳脫符號。則檢索不到結果,甚至會報錯的。 案例:用$ 去匹配 “abc$(" 會怎樣?

        在Java的正規表示式中,兩個\ 代表其他語言中的一個

        需要用到跳脫符號的字元有以下 : " .  *  +  ()  $  /    ?  [  ]  ^  {  } "

二、正則語法

1、字元匹配符、選擇匹配符

▶ 基本介紹

▶ 程式碼實現

String content = "a11c8abc _ABCy @";
 
String regStr = "[a-z]"; //匹配 a-z 之間任意一個字元
 
String regStr = "[A-Z]"; //匹配 A-Z 之間任意一個字元
 
String regStr = "abc"; //匹配 abc 字串[預設區分大小寫]
 
String regStr = "(?i)abc"; //匹配 abc 字串[不區分大小寫]
 
String regStr = "[0-9]"; //匹配 0-9 之間任意一個字元
 
String regStr = "[^a-z]"; //匹配 不在 a-z 之間任意一個字元
 
String regStr = "[^0-9]"; //匹配 不在 0-9 之間任意一個字元
 
String regStr = "[abcd]"; //匹配 在 abcd 中任意一個字元
 
String regStr = "\D"; //匹配 不在 0-9 的任意一個字元
 
String regStr = "\w"; //匹配 大小寫英文字母, 數位,下劃線
 
String regStr = "\W"; //匹配 等價於 [^a-zA-Z0-9_]
 
// \s 匹配任何空白字元(空格,製表符等)
String regStr = "\s";
 
// \S 匹配任何非空白字元 ,和\s 剛好相反
String regStr = "\S";
 
//. 匹配出 n 之外的所有字元,如果要匹配.本身則需要使用 \.
String regStr = ".";
//當建立 Pattern 物件時,指定 Pattern.CASE_INSENSITIVE, 表示匹配是不區分字母大小寫. 
Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);

▶ 選擇匹配符

String content = "study hard"; 
String regStr = "t|a|r";

2、限定符

▶ 基本介紹

▶ 程式碼實現

String content = "a211111aaaaaahello";
 
String regStr = "a{3}"; // 表示匹配 aaa
String regStr = "1{4}"; // 表示匹配 1111
String regStr = "\d{2}"; // 表示匹配 兩位的任意數位字元
 
//細節:java 匹配預設貪婪匹配,即儘可能匹配多的
String regStr = "a{3,4}"; //表示匹配 aaa 或者 aaaa
String regStr = "1{4,5}"; //表示匹配 1111 或者 11111
String regStr = "\d{2,5}"; //匹配 2 位數或者 3,4,5
 
//1+
String regStr = "1+"; //匹配一個 1 或者多個 1
String regStr = "\d+"; //匹配一個數位或者多個數位
 
//1*
String regStr = "1*"; //匹配 0 個 1 或者多個 1
 
//遵守貪婪匹配
String regStr = "a1?"; //匹配 a 或者 a1

3、定位符

▶ 基本介紹

▶ 程式碼實現

String content = "123-abc sldkjfs s dfsjf";
 
String content = "123-abc";
 
//以至少 1 個數位開頭,後接任意個小寫字母的字串
String regStr = "^[0-9]+[a-z]*";
 
//以至少 1 個數位開頭, 必須以至少一個小寫字母結束
String regStr = "^[0-9]+\-[a-z]+$";
 
//表示匹配邊界的 han[這裡的邊界是指:被匹配的字串最後,也可以是空格的子字串的後面]
String regStr = "han\b";
 
//和\b 的含義剛剛相反
String regStr = "han\B";

4、分組

▶ 基本介紹

▶ 程式碼實現

String content = "hello world s7789 nn1189han";
 
//命名分組: 即可以給分組取名
String regStr = "(?<g1>\d\d)(?<g2>\d\d)";//匹配 4 個數位的字串
 
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
 
while (matcher.find()) {
    System.out.println("找到=" + matcher.group(0));
    System.out.println("第 1 個分組內容=" + matcher.group(1));
    System.out.println("第 1 個分組內容[通過組名]=" + matcher.group("g1"));
    System.out.println("第 2 個分組內容=" + matcher.group(2));
    System.out.println("第 2 個分組內容[通過組名]=" + matcher.group("g2"));
}

三、常用類

1、基本介紹

▶ 概述

  ▷ java.util.regex 包主要包括以下三個類Pattern 類、Matcher 類和 PatternSyntaxException   ▷ Pattern 類
        pattern 物件是一個正規表示式物件。Pattern 類沒有公共構造方法。要建立一個Pattern 物件 呼叫其公共靜態方法,它返回一個Pattern 物件。該方法接受一個正規表示式作為它的第一個引數,比如: Pattern r=Pattern.compile(pattern);
  ▷ Matcher類
        Matcher物件是對輸入字串進行解釋和匹配的引擎。 與Pattern 類一樣, Matcher 也沒有公共構造方法。 你需要呼叫 Pattern 物件的 matcher方法來獲得一個 Matcher物件
  ▷ PatternSyntaxException
        PatternSyntaxException 是一個非強制異常類, 它表示一個正規表示式模式中的語法錯誤。

▶ 程式碼範例

public class PatternMethod {
    public static void main(String[] args) {
        String content = "hello abc hello, 努力學習";
 
        //String regStr = "hello";
 
        String regStr = "hello.*";
 
        boolean matches = Pattern.matches(regStr, content);
 
        System.out.println("整體匹配= " + matches);
    }
}

▶ Matcher 常用類

public class MatcherMethod {
    public static void main(String[] args) {
        String content = "hello edu jack edutom hello smith hello edu edu";
 
        String regStr = "hello";
 
        Pattern pattern = Pattern.compile(regStr);
 
        Matcher matcher = pattern.matcher(content);
 
        while (matcher.find()) {
            System.out.println(matcher.start());
            System.out.println(matcher.end());
            System.out.println("找到: " + content.substring(matcher.start(), matcher.end()));
        }
 
        //整體匹配方法,常用於,去校驗某個字串是否滿足某個規則
        System.out.println("整體匹配=" + matcher.matches());
 
        //完成如果 content 有 edu 替換成 努力學習
        regStr = "edu";
        pattern = Pattern.compile(regStr);
        matcher = pattern.matcher(content);
 
        //注意:返回的字串才是替換後的字串 原來的 content 不變化
        String newContent = matcher.replaceAll("努力學習");
 
        System.out.println("newContent=" + newContent);
        System.out.println("content=" + content);
    }
}

2、分組、捕獲、反向參照

▶ 基本介紹

1、分組

        我們可以用圓括號組成一個比較複雜的匹配模式,那麼一個圓括號的部分我們可以看作是一個子表示式(一個分組)。

2、捕獲

        把正規表示式中子表示式(分組匹配)的內容,儲存到記憶體中以數位編號或顯式命名的組裡, 方便後面參照, 從左向右,以分組的左括號為標誌,第一個出現的分組的組號為1,第二個為2,以以此類推,組0代表的是整個正則式。

3、反向參照

        圓括號的內容被捕獲後,可以在這個括號後被使用, 從而寫出一個比較實用的匹配式,這個我們稱為反向參照,這種參照既可以是在正規表示式內部,也可以是在正規表示式外部,內部反向參照\分組號,外部反向參照$分組號。

▶ 經典案例

public class RegExp13 {
    public static void main(String[] args) {
        String content = "我....我要....學學學學....程式設計 java!";
 
        //1. 去掉所有的.
        Pattern pattern = Pattern.compile("\.");
        Matcher matcher = pattern.matcher(content);
        content = matcher.replaceAll("");
 
        //2. 去掉重複的字 我我要學學學學程式設計 java!
        //(1) 使用 (.)\1+
        //(2) 使用 反向參照$1 來替換匹配到的內容
        // 注意:因為正規表示式變化,所以需要重置 matcher
 
        pattern = Pattern.compile("(.)\1+");//分組的捕獲內容記錄到$1
 
        matcher = pattern.matcher(content);
 
        //使用 反向參照$1 來替換匹配到的內容
        content = matcher.replaceAll("$1");
 
        System.out.println("content=" + content);
    }
}

3、String 類中使用正規表示式

▶ 替換功能

        String 類:  public String replaceAll(String regex,String replacement)

▶ 判斷功能

        String 類:  public boolean matches(String regex){} // 使用 Pattern Matcher

▶ 分割功能

        String 類:  public String[] split(String regex)

▶ 程式碼範例

String content = "2000 年 5 月,JDK1.3、JDK1.4 和 J2SE1.3 相繼釋出。";
 
//使用正規表示式方式,將 JDK1.3 和 JDK1.4 替換成 JDK
content = content.replaceAll("JDK1\.3|JDK1\.4", "JDK");
 
System.out.println(content);
//要求 驗證一個 手機號, 要求必須是以 138 139 開頭的
content = "13888889999";
 
if (content.matches("1(38|39)\d{8}")) {
    System.out.println("驗證成功");
} else {
    System.out.println("驗證失敗");
}
//要求按照 # 或者 - 或者 ~ 或者 數位 來分割
content = "hello#abc-jack12smith~北京";
 
String[] split = content.split("#|-|~|\d+");
 
for (String s : split) {
    System.out.println(s);
}

 總結

到此這篇關於正規表示式基礎語法以及如何應用的文章就介紹到這了,更多相關正規表示式基礎語法及應用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com