Java 正則表達式

正則表達式的語法

元字符-轉義號\\

提示:在Java中兩個 \\ 相當於其他語言中的一個\

需要用到轉義符的字符有以下幾個:

. * + () $ / \ ? [] ^ {}

如果匹配條件只有一個 ‘.’ 的話,意思是匹配所有字符

元字符-字符匹配符

符號 含義 示例 解釋
[] 可接受的字符列表 [efgh] e,f,g,h中的任意一個字符
[^] 不接收的字符列表 [^abc] 除a,b,c之外的任意一個字符,包括數字和特殊符號
連字符 A-Z 任意單個大寫字母
. 匹配除 \n 以外的任意一個字符 a..b 以a開頭,b結尾,中間包括2個任意字符的長度為4的字符串
\\d 匹配單個數字字符,相當於[0-9] \\d{3}(\\d)? 包含3個或4個數字的字符串
\\D 匹配單個非數字字符,相當於[^0-9] \\D(\\d)* 以單個非數字字符夾頭,後接任意個數數字字符串
\\w 匹配單個數字,大小寫字母字符,相當於[0-9a-zA-Z] \\d{3}\\w{4} 以3個數字是字符開頭的長度為7的數字字母字符串
\\W 匹配單個非數字,大小寫字母字符,相當於[^0-9a-zA-Z] \\W+\\d{2} 以至少1個非數字字母字符開頭,2個數字字符結尾的字符串
\\s 匹配任何空白字符(空格,製表符等)
\\S 匹配任意非空白字符,和\\s整好相反

一些應用實例

[a-z], [A-Z], [1-9]的說明

表示可以匹配a-z的任意一個字符, A-Z的任意一個字符,1-9的任意一個字符

[^a-z], [^A-Z], [^1-9]的說明

表示匹配的不是a-z的任意一個字符, 匹配的不是A-Z的任意一個字符,匹配的不是1-9的任意一個字符

[abcd] [^abcd]

表示匹配的是abcd中的任意一個字符,匹配的不是abcd中的任意一個字符

.

匹配 \n 之外的所有字符,如果要匹配 . 本身, 則需使用 \.

java正則表達式默認是區分字母大小寫的,如何實現不區分大小寫呢?以”abc”舉例

  • (?i)abc 表示 abc 不區分大小寫
  • a(?i)bc 表示 bc 不區分大小寫
  • a((?i)b)c 表示只有 b 不區分大小寫
  • Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);

元字符-選擇匹配符 |

例子:

public static void main(String[] args) {
        String content = "abc 555 666";
        String reg = "abc|555|666";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()) {
            System.out.println(matcher.group(0));
        }
    }
結果返回 abc 555 666

元字符-限定符

用於指定】其前面的字符和組合項連續出現多少次

符號 含義 示例 說明 匹配輸入
* 指定字符重複0次或n次(無要求) (abc)* 僅包含任意個abc的字符串 abc, abcabcabc
+ 指定字符重複1次或n次(至少一次) m+(abc)* 以至少一個m開頭,後接任意個abc的字符串 m,mabc,mabcabc
? 指定字符重複0次或1次(最多1次) m+abc? 以至少一個m開頭,後接ab或abc的字符串 mab,mabc,mmmab,mmabc
{n} 只能輸入n個字符 [abcd]{3} 由abcd中字母組成的任意長度為3的字符串 abc,adc, bcd
{n,} 指定至少n個匹配 [abcd]{3,} 由abcd組成的至少為3的字符串 abc,adc,abcdddd
{n,m} 指定至少n個但不超過m個匹配 [abcd]{3,5} 由abcd中的字母組成的任意長度不小於3,不大於5的字符串 abc,abdc,addcb

細節:關於上述的{n,m},java進行匹配的時候默認是貪婪匹配,即盡量匹配多的,如果想要使其非貪婪匹配的話,需要在限定符後面加 ?

元字符-定位符

規定要匹配的字符串出現的位置,比如在字符串的開始還是在結束的位置

符號 含義 示例 說明 匹配輸入
^ 指定起始字符 ^ [0-9]+[a-z]* 以至少1個數字開頭,後接任意個小寫字母的字符串 123, 6aa, 55edf
$ 指定結束字符 ^ [0-9]\-[a-z]+$ 以1個數字開頭後接連字符「-」,並以至少1個小寫字母結尾的字符串 1-a
\\b 匹配目標字符換的邊界 han\\b 這裡說的字符串的邊界指的是子串間有空格,或者是目標字符串的結束位置 hanshunpingsphan nnhan
\\B 匹配目標字符串的非邊界 han\\B 和\\b正好相反 hanshunpingsphan nnhan

解釋一下 \\b:指的是一某個字符串結尾(空格也算作結尾),例如:”hanshunpingsphan nnhan”,則輸出 兩個 “han”

分組

常用分組構造形式 說明
(pattern) 非命名捕獲。捕獲匹配的子字符串。編號為零的第一個捕獲是由整個正則表達式模式匹配的文本,其它捕獲結果則根據左括號的順序從1開始自動編號
(?pattern) 命名捕獲。將匹配的子字符串捕獲到一個組名稱或編號名稱中。用於name的字符串不能包含任何標點符號,並且不能以數字開頭。可以使用單引號替代尖括號,例如(?’name’)

舉例說明

未命名捕獲

public static void main(String[] args) {
        String content = "dhviaoohdidjkad1335njdoaifjwoi1516ndkfnaeo51561";
        String reg = "(\\d\\d)(\\d\\d)"; //匹配四個數字的字符串
        Pattern pattern = Pattern.compile(reg);
        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(3));
        }
    }

命名分組:可以給分組取名

public static void main(String[] args) {
        String content = "dhviaoohdidjkad1335njdoaifjwoi1516ndkfnaeo51561";
        String reg = "(?<g1>\\d\\d)(?<g2>\\d\\d)";
        Pattern pattern = Pattern.compile(reg);
        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("g1"));
            System.out.println("第二個分組的內容" + matcher.group(2));
            System.out.println("第二個分組的內容[通過組名]" + matcher.group("g2"));
        }
    }

給分組取了個名字,可以通過編號來取,也可以通過去的組名來取

特別分組

常用分組構造形式 說明
(?:pattern) 匹配pattern但不捕獲該匹配的子表達式,即它是一個非捕獲匹配,不存儲供以後使用的匹配。這對於用”or”字符(
(?=pattern) 它是一個非捕獲匹配。例如,”Windows (=95
(?!pattern]) 該表達式匹配不處於匹配pattern的字符串的起始點的搜索字符串。它是一個非捕獲匹配。例如,”Windows (?!95

(?:pattern)

public static void main(String[] args) {
        String content = "12132韓順平教育 fewafew韓順平老師 gdgd韓順平同學";
        //String reg = "韓順平教育|韓順平老師|韓順平同學";
        //上面的寫法等價於非捕獲分組,注意:不能 matcher.group(1)
        String reg = "韓順平(?:教育|老師|同學)";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()) {
            System.out.println(matcher.group(0));
        }
    }

(?=pattern)

public static void main(String[] args) {
        String content = "12132韓順平教育 fewafew韓順平老師 gdgd韓順平同學";
        //下面是非捕獲分組,也不能使用 matcher.group(1)
        String reg = "韓順平(?=教育|老師)";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()) {
            System.out.println(matcher.group(0));
        }
    }

(?!pattern)

public static void main(String[] args) {
        String content = "12132韓順平教育 fewafew韓順平老師 gdgd韓順平同學";
        //下面是非捕獲分組,也不能使用 matcher.group(1)
        String reg = "韓順平(?!教育|老師)";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()) {
            System.out.println(matcher.group(0));
        }
    }

正則表達式三個常用類

Pattern 類

pattern對象是一個正則表達式對象。Pattern 類沒有公共構造方法。要創建一個 Pattern對象,調用其公共靜態方法,它返回一個 Pattern對象。該方法接受一個正則表達式作為它的第·一個參數,比如: Patternr = Pattern.compile(pattern);

部分方法

整體匹配: Pattern.matches()(想起驗證某個字符串是否符合條件,返回的是真或者假)

public static void main(String[] args) {
        String content = "hello abc 111";
        String reg = "hello.*";
        boolean matches = Pattern.matches(reg, content);
        System.out.println("匹配結果: " +  matches);
    }

Matcher 類

Matcher 對象是對輸入字符串進行解釋和匹配的引擎。與Patterr類一樣,Matcher 也沒有公共構造方法。你需要調用 Pattern 對象的 matcher 方法來獲得一個 Matcher 對象

方法一覽

public int start()返回以前匹配的初始索引。
public int start(int group)返回在以前的匹配操作期間,由給定組所捕獲的子序列的初始索引public int end()返回最後匹配字符之後的偏移量。
public int end(int group)返回在以前的匹配操作期間,由給定組所捕獲子序列的最後字符之後的偏移量。
public boolean lookingAt()嘗試將從區域開頭開始的輸入序列與該模式匹配。
public boolean lookingAt()嘗試將從區域開頭開始的輸入序列與該模式匹配。
public boolean lookingAt()嘗試將從區域開頭開始的輸入序列與該模式匹配。
public boolean lookingAt()嘗試將從區域開頭開始的輸入序列與該模式匹配。
public Matcher appendReplacement(StringBuffer sb, String replacement)實現非終端添加和替換步驟。
public StringBuffer appendTail(StringBuffer sb)實現終端添加和替換步驟。
public String replaceAll(String replacement)替換模式與給定替換字符串相匹配的輸入序列的每個子序列。(返回的字符串才是改變之後的字符串)
public String replaceFirst(String replacement)替換模式與給定替換字符串匹配的輸入序列的第一個子序列。
public static String quoteReplacement(String s)返回指定字符串的字面替換字符串。這個方法返回一個字符串,就像傳遞給Matcher類的appendReplacement方法一個字面字符串一樣工作。
public Matcher appendReplacement(StringBuffer sb, String replacement)實現非終端添加和替換步驟。
public StringBuffer appendTail(StringBuffer sb)實現終端添加和替換步驟。

PatternSyntaxException 類

PatternSyntaxException是一個非強制異常類,它表示一個正則表達式模式中的語法錯誤。

分組,捕獲,反向引用之間的關係

介紹

1.分組
我們可以用圓括號組成一個比較複雜的匹配模式,那麼一個圓括號的部分我們可以看作是一個子表達式/一個分組。
2捕獲
把正則表達式中子表達式/分組匹配的內容,保存到內存中以數字編號或顯式命名的組裡,方便後面引用,從左向右,以分組的左括號為標誌,第一個出現的分組的組號為1,第二個為2,以此類推。組0代表的是整個正則式
3.反向引用
圓括號的內容被捕獲後,可以在這個括號後被使用,從而寫出一個比較實用的匹配模式,這個我們稱為反向引用,這種引用既可以是在正則表達式內部,也可以是在正則表達式外部,內部反向引用\\\分組號,外部反向引用$分組號

提出問題:給你一段文本,請你找出所有四個數字連在一起的子串,並且這四個數字要滿足④第1位與·第4位相同②第2位與第3位相同,比如1221,5775 ..
反向引用案例:

public static void main(String[] args) {
        
        String content = "hello abc 1111 afda2332";
        //下面是非捕獲分組,也不能使用 matcher.group(1)
        String reg = "(\\d)(\\d)\\2\\1";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()) {
            System.out.println("匹配結果: " +  matcher.group(0));
        }
}

案例:
問題:把類似”我…我要…學學學學…編程java!” 利用正則表達式改成 “我要學編程java!”

public static void main(String[] args) {
        
        String content = "我...我要...學學學學...編程java!";
        // 1. 去掉所有的 .
        Pattern pattern = Pattern.compile("\\.");
        Matcher matcher = pattern.matcher(content);
        content = matcher.replaceAll("");
        System.out.println("content : " + content);
        // 2. 去掉重複的字 我我要學學學學編程java!

        // 思路;
        // (1) 使用 (.)\\1+ 匹配相鄰個數大於等於2的子串
        // (2) 使用反向引用$1 來替換匹配到的內容
        //注意:這裡正則表達式變化,所以要重置 matcher
        //pattern = Pattern.compile("(.)\\1+");  //分組的捕獲內容記錄到$1
        //matcher = pattern.matcher(content);
        //while (matcher.find()) {
        //    System.out.println("找到 = " + matcher.group(0));
        //}
        //使用反向引用 $1 來替換匹配到的內容
        //content = matcher.replaceAll("$1");
        //System.out.println("content = " + content);

        // (3) 使用一條語句去掉重複的字
        content = Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
        System.out.println("content = " + content);
    }

String 類中也可以直接使用正則表達式

替換功能

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

判斷功能

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

分割功能

String 類 public String[] split(String regex)

Tags: