正則表達(dá)式使用規(guī)則

1.單個(gè)字符的匹配規(guī)則如下:

正則表達(dá)式 規(guī)則 可以匹配
A 指定字符 A
\u548c 指定Unicode字符
. 任意字符 ab,&,0
\d 數(shù)字0~9 0~9
\w 大小寫字母,數(shù)字和下劃線 a`z`,`A`Z,0~9,_
\s 空格、Tab鍵 空格,Tab
\D 非數(shù)字 a,A&,_,……
\W 非\w &,@,……
\S 非\s aA,&,_,……

2.多個(gè)字符的匹配規(guī)則如下

正則表達(dá)式 規(guī)則 可以匹配
A* 任意個(gè)數(shù)字符 空,AAAAAA,……
A+ 至少1個(gè)字符 A,AA,AAA,……
A? 0個(gè)或1個(gè)字符 空,A
A{3} 指定個(gè)數(shù)字符 AAA
A{2,3} 指定范圍個(gè)數(shù)字符 AA,AAA
A{2,} 至少n個(gè)字符 AA,AAA,AAAA,……
A{0,3} 最多n個(gè)字符 空,A,AA,AAA

3.匹配指定范圍

比如1A2b3c,我們可以這樣寫:[0-9a-fA-F],它表示一共可以匹配以下任意范圍的字符:
0-9:字符0~9;
a-f:字符a~f;
A-F:字符A~F。

3.1排除法

? ^ 不包含指定范圍的字符

  • 假設(shè)我們要匹配任意字符,但不包括數(shù)字,可以寫[^1-9]{3}

    • 可以匹配"ABC",因?yàn)椴话址?code>1~9;

    • 可以匹配"A00",因?yàn)椴话址?code>1~9;

    • 不能匹配"A01",因?yàn)榘址?code>1;

    • 不能匹配"A05",因?yàn)榘址?code>5。

4.或規(guī)則匹配

|連接的兩個(gè)正則規(guī)則是規(guī)則,例如,AB|CD表示可以匹配ABCD

5.實(shí)用括號

現(xiàn)在我們想要匹配字符串learn java、learn phplearn go怎么辦?一個(gè)最簡單的規(guī)則是learn\sjava|learn\sphp|learn\sgo,但是這個(gè)規(guī)則太復(fù)雜了,可以把公共部分提出來,然后用(...)把子規(guī)則括起來表示成learn\\s(java|php|go)。

var 使用括號匹配大寫 = "learn\\s([Jj]ava|[Gg]o|[Pp]hp)";
//匹配字符串learn Java、learn Php和learn Go的大小寫

6.分組匹配

正則匹配區(qū)號-電話號碼這個(gè)規(guī)則

\d{3,4}\-\d{6,8}

如果需要提取區(qū)號和電話號碼,需要將要提取的規(guī)則使用括號分組,把上述正則表達(dá)式變?yōu)?code>(\d{3,4})\-(\d{6,8})

public class Main {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
        Matcher m = p.matcher("010-12345678");
        if (m.matches()) {
            System.out.println(m.group(0));//010-12345678
            String g1 = m.group(1);////010
            String g2 = m.group(2);//12345678
            System.out.println(g1);
            System.out.println(g2);
        } else {
            System.out.println("匹配失敗!");
        }
    }
}

使用Matcher時(shí),必須首先調(diào)用matches()判斷是否匹配成功,匹配成功后,才能調(diào)用group()提取子串。

例子:
從字符串23:01:59提取時(shí)、分、秒

var time = "([0-1]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)";
Pattern p1 = Pattern.compile(time);
Matcher m1 = p1.matcher("23:01:59");
   if (m1.matches()) {
         System.out.println(m1.group(1));
         System.out.println(m1.group(2));
         System.out.println(m1.group(3));
   } else {
        System.out.println("匹配失敗");
   }

7.非貪婪匹配

給定一個(gè)字符串表示的數(shù)字,判斷該數(shù)字末尾0的個(gè)數(shù)??梢院苋菀椎貙懗鲈撜齽t表達(dá)式:(\d+)(0*)

  • "123000":3個(gè)0 期望結(jié)果: 123 000 實(shí)際結(jié)果:"123000" ""

  • "10100":2個(gè)0 期望結(jié)果: 101 00 實(shí)際結(jié)果:"10100" ""

  • "1001":0個(gè)0 期望結(jié)果: 1001 "" 實(shí)際結(jié)果:"1001" ""

這是因?yàn)檎齽t表達(dá)式默認(rèn)使用貪婪匹配:任何一個(gè)規(guī)則,它總是盡可能多地向后匹配,因此,\d+總是會把后面的0包含進(jìn)來。

要讓\d+盡量少匹配,讓0*盡量多匹配,我們就必須讓\d+使用非貪婪匹配。在規(guī)則\d+后面加個(gè)?即可表示非貪婪匹配。

改寫正則表達(dá)式如下(\d+?)(0*)" 因此,給定一個(gè)匹配規(guī)則,加上?后就變成了非貪婪匹配。

我們再來看這個(gè)正則表達(dá)式(\d??)(9*),注意\d?表示匹配0個(gè)或1個(gè)數(shù)字,后面第二個(gè)?表示非貪婪匹配,因此,給定字符串"9999",匹配到的兩個(gè)子串分別是"""9999",因?yàn)閷τ?code>\d?來說,可以匹配1個(gè)9,也可以匹配0個(gè)9,但是因?yàn)楹竺娴?code>?表示非貪婪匹配,它就會盡可能少的匹配,結(jié)果是匹配了0個(gè)9

8.搜索和替換

8.1 分割字符串

System.out.println(Arrays.toString("a b c".split("\\s")));//[a, b, c]
System.out.println(Arrays.toString("a b  c".split("\\s")));//[a, b, "", c]
System.out.println(Arrays.toString("a,b ;; c".split("[\\,\\s\\;]+")));//[a, b, c]

8.2 搜索字符串

String s = "the quick brown fox jumps over the lazy dog.";
Pattern p3 = Pattern.compile("\\wo\\w");// \w匹配[A-Za-z0-9_]
Matcher m3 = p3.matcher(s);
while (m3.find()) {
   String sub = s.substring(m3.start(), m3.end());
   System.out.println(sub);
   //row fox dog
}

我們獲取到Matcher對象后,不需要調(diào)用matches()方法(因?yàn)槠ヅ湔麄€(gè)串肯定返回false),而是反復(fù)調(diào)用find()方法,在整個(gè)串中搜索能匹配上\\wo\\w規(guī)則的子串,并打印出來。這種方式比String.indexOf()要靈活得多,因?yàn)槲覀兯阉鞯囊?guī)則是3個(gè)字符:中間必須是o,前后兩個(gè)必須是字符[A-Za-z0-9_]。

8.3 替換字符串

String s2 = "The     quick\t\t brown   fox  jumps   over the  lazy dog.";
String r = s2.replaceAll("\\s+", " ");//將多個(gè)空格替換成一個(gè)
System.out.println(r); // "The quick brown fox jumps over the lazy dog."

8.4 反向引用

String s3 = "the quick brown fox jumps over the lazy dog.";
String r2 = s3.replaceAll("\\s([a-z]{4})\\s", "<b>$1</b>");
System.out.println(r2);//the quick brown fox jumps<b>over</b>the<b>lazy</b>dog.

它實(shí)際上把任何4字符單詞的前后用<b>xxxx</b>括起來。實(shí)現(xiàn)替換的關(guān)鍵就在于" <b>$1</b> ",它用匹配的分組子串([a-z]{4})替換了$1。

8.5 使用Map替換模板中的值

        HashMap<String, String> map = new HashMap<>();
        map.put("name", "Mary");
        map.put("lang", "Java");
        String model = "Hello, ${name}! You are learning ${lang}!";
        Pattern pt = Pattern.compile("\\$\\{([a-z]+)}");
        Matcher mt = pt.matcher(model);
        StringBuilder sb = new StringBuilder();
        while (mt.find()) {
           //0->${name}  1->name
           //0->${lang}  1->lang
           //0 代表整個(gè)匹配的字段  1代表匹配字段中的第一個(gè)分組
           mt.appendReplacement(sb, map.get(mt.group(1)));
        }
        mt.appendTail(sb);
        System.out.println(sb.toString());
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容