Java正則表達式


一、概述

  正則表達式是一串描述一個字符序列的字符,可以用來查找其他字符序列中的匹配項。支持正則表達式處理的是兩個類:Pattern和Matcher,使用Pattern定義正則表達式,使用Matcher匹配其他序列中的模式。

二、創建正則表達式

  創建正則表達式就是創建一個特殊的字符串。

  正則表達式的編譯表達形式:指定為字符串的正則表達式必須首先被編譯為此類的實例,然后將得到的模式用於創建Matcher對象。執行匹配所涉及的所有狀態都駐留在匹配器中,多個匹配器可以共享同一模式。

public class Test
{
    public static void main(String[] args)
    {
        Pattern pat=Pattern.compile("a*b");
        Matcher  mat=pat.matcher("aaaaab");
        if(mat.matches())
        {
            System.out.print("匹配");
        }
    }
}

  上述代碼等同於

if("aaaaab".matches("a*b"))
    {
        System.out.print("匹配");
    }

  Pattern對象可以多次使用,如果某個正則表達式只需要一次使用,可直接使用Pattern類的靜態matches方法。

  正則表達式的構造摘要:

構造 匹配
字符
x 字符 x
\\ 反斜線字符
\0n 帶有八進制值 0 的字符 n (0 <= n <= 7)
\0nn 帶有八進制值 0 的字符 nn (0 <= n <= 7)
\0mnn 帶有八進制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 帶有十六進制值 0x 的字符 hh
\uhhhh 帶有十六進制值 0x 的字符 hhhh
\t 制表符 ('\u0009')
\n 新行(換行)符 ('\u000A')
\r 回車符 ('\u000D')
\f 換頁符 ('\u000C')
\a 報警 (bell) 符 ('\u0007')
\e 轉義符 ('\u001B')
\cx 對應於 x 的控制符
字符類
[abc] abc(簡單類)
[^abc] 任何字符,除了 abc(否定)
[a-zA-Z] azAZ,兩頭的字母包括在內(范圍)
[a-d[m-p]] admp[a-dm-p](並集)
[a-z&&[def]] def(交集)
[a-z&&[^bc]] az,除了 bc[ad-z](減去)
[a-z&&[^m-p]] az,而非 mp[a-lq-z](減去)
預定義字符類
. 任何字符(與行結束符可能匹配也可能不匹配)
\d 數字:[0-9]
\D 非數字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 單詞字符:[a-zA-Z_0-9]
\W 非單詞字符:[^\w]
邊界匹配器
^ 行的開頭
$ 行的結尾
\b 單詞邊界
\B 非單詞邊界
\A 輸入的開頭
\G 上一個匹配的結尾
\Z 輸入的結尾,僅用於最后的結束符(如果有的話)
\z 輸入的結尾
Greedy 數量詞
X? X,一次或一次也沒有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n
X{n,} X,至少 n
X{n,m} X,至少 n 次,但是不超過 m
Reluctant 數量詞
X?? X,一次或一次也沒有
X*? X,零次或多次
X+? X,一次或多次
X{n}? X,恰好 n
X{n,}? X,至少 n
X{n,m}? X,至少 n 次,但是不超過 m
Possessive 數量詞
X?+ X,一次或一次也沒有
X*+ X,零次或多次
X++ X,一次或多次
X{n}+ X,恰好 n
X{n,}+ X,至少 n
X{n,m}+ X,至少 n 次,但是不超過 m
Logical 運算符
XY X 后跟 Y
X|Y XY
(X) X,作為捕獲組

  正則表達式支持的數量標識符有如下幾種模式:

  Greedy(貪婪模式):默認情況下數量表示符采用貪婪模式,該方式會一直匹配下去直到無法匹配為止。

  Reluctant(勉強模式):用問號后綴(?)表示。它只會匹配最少的字符。

  Possessive(占有模式):用加號后綴(+)表示,一般較少使用。

  eg:

public class RegExp
{
    public static void main(String[] args)
    {
        Pattern pat1=Pattern.compile("\\w.*ab");
        Pattern pat2=Pattern.compile("\\w.*?ab");
        Matcher mat1=pat1.matcher("bbbbab aaab jjjjj is");
        Matcher mat2=pat2.matcher("bbbbab aaab jjjjj is");
        System.out.println("-----貪婪模式-------");
        while(mat1.find())
        {
            System.out.println(mat1.group());  //貪婪模式下會一直匹配,輸出"bbbbab aaab"
        }
        System.out.println("-----勉強模式-------");
        while(mat2.find())
        {
            System.out.println(mat2.group()); //勉強模式下會最小匹配,輸出"bbbbab '換行'  aaab"
        }
    }
}

  輸出結果:

  

三、使用正則表達式

  Pattern類沒有定義構造函數,是在調用compile()方法時創建模式。

  Matcher類也沒有構造函數,而是調用Pattern定義的matches方法時創建一個Matcher,只要創建了Mather就可以使用它的方法執行各種模式匹配操作。

  • matches 方法嘗試將整個輸入序列與該模式匹配。

  • lookingAt 嘗試將輸入序列從頭開始與該模式匹配。

  • find 方法掃描輸入序列以查找與該模式匹配的下一個子序列。

  每個方法都返回一個表示成功或者失敗的布爾值。通過查詢匹配器的狀態可以獲取更多關於成功匹配的信息。

  Matcher類提供了很多常用的方法,下面代碼簡單進行解釋其用法:

public class RegExp
{
    public static void main(String[] args)
    {
        Pattern pat=Pattern.compile("\\w.*?ab");
        Matcher mat=pat.matcher("bbbbab aa isabc");
        if(mat.matches())//嘗試將整個區域與模式匹配
        {
            System.out.println("模式匹配");
        }
        else
        {
            System.out.println("模式不匹配");
        }
        mat.reset();//重置匹配器
        while(mat.find())  //嘗試查找與該模式匹配的輸入序列的下一個子序列
        {
            System.out.println(mat.group());//返回由以前匹配操作所匹配的輸入子序列
            System.out.println("開始位置:"+mat.start()+"---"+"結束位置:"+mat.end());//start()返回以前匹配的初始索引,end()返回最后匹配字符之后的偏移量
        }
        mat.reset();
        if(mat.lookingAt())//嘗試將從區域開頭開始的輸入序列與該模式匹配
        {
            System.out.println("模式匹配");
        }
        else
        {
            System.out.println("模式不匹配");
        }
    }
}

  運行結果:

  

  此外,還可以利用正則表達式對目標字符串進行分割、查找、替換等操作。

  eg:

public class Test
{
    public static void main(String[] args)
    {
        Pattern pat=Pattern.compile("\\w.*?ab");
        Matcher mat=pat.matcher("bbbbab aa isabc");
        System.out.println(mat.replaceAll("替換后"));//替換模式與給定替換字符串相匹配的輸入序列的每個子序列
        System.out.println(mat.replaceFirst("替換后"));// 替換模式與給定替換字符串匹配的輸入序列的第一個子序列
        Pattern p=Pattern.compile("[ , . !]");//圍繞此模式的匹配拆分給定輸入序列
        String[] str=p.split("one two,alpha9!done.");//遇到空格、逗號、頓號和感嘆號就分割並將結果保存在str字符串數組中
        for(int i=0;i<str.length;i++)
            System.out.println(str[i]);  
    }
}

打印結果為:

四、正則表達式的簡單應用

1、打印某頁面中出現的所有郵箱地址

public class EmailReg
{
    public static void main(String[] args)
    {
        BufferedReader br=null;
        try
        {
            br=new BufferedReader(new FileReader("C:\\Users\\Administrator\\Desktop\\resource2.html"));
            String line="";
            while((line=br.readLine())!=null)
                {
                    parse(line);
                }
        } 
        catch (FileNotFoundException e)
        {
        
            e.printStackTrace();
        } 
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(br!=null)
            {
                try
                {
                    br.close();
                    br=null;
                } 
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    private static void parse(String line)
    {
        Pattern pat=Pattern.compile("\\w{3,20}+@\\w+\\.(com|org|cn|net|gov)");
        Matcher mat=pat.matcher(line);
        while(mat.find())
        {
            System.out.println(mat.group());
        }
    }
}

2、統計某文件夾的.java文件的代碼行數、注釋行數、空白行行數

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class WordCount
{
     static long wordsNumber=0;
     static long emptyNumber=0;
     static long zhushiNumber=0;
    public static void main(String[] args)
    {
            File f=new File("D:\\src\\"); //文件夾地址
            File[] codeFiles=f.listFiles();
            for(File child:codeFiles)
            {
                if(child.getName().matches(".*\\.java$")) //如果是.java文件,則進行處理
                {
                    parse(child);//處理單個文件
                }
            }
                System.out.println("注釋的行數為:"+zhushiNumber);
                System.out.println("空行的行數為:"+emptyNumber);
                System.out.println("代碼行的行數為:"+wordsNumber);
    }
    private static void parse(File child)
    {
            BufferedReader br=null;
            boolean comment=false;
            String line="";
            try
            {
                br=new BufferedReader(new FileReader(child));
                while((line=br.readLine())!=null)
                {
                    line=line.trim();
                    if(line.matches("^[\\s&&[^\\n]]*$"))  //匹配空行
                        emptyNumber++;
                     else if (line.startsWith("/*") && !line.endsWith("*/"))   //以/*開頭,不以*/結尾,表明有多行注釋
                     {
                         zhushiNumber ++;
                        comment = true;    
                    } 
                     else if (line.startsWith("/*") && line.endsWith("*/")) //以/*開頭,並且以*/結尾
                     {
                        zhushiNumber ++;
                    } 
                     else if (true == comment) 
                     {
                        zhushiNumber ++;
                        if(line.endsWith("*/")) 
                        {
                            comment = false;
                        }
                    } 
                     else if (line.startsWith("//"))   ////結尾為注釋行
                     {
                        zhushiNumber ++;
                    }
                    else
                        wordsNumber++;
                }
            } 
            catch (IOException e)
            {
                // TODO 自動生成的 catch 塊
                e.printStackTrace();
            }
        }
    }

運行結果圖:

五、常用表達式總結

  此部分內容為轉載,來自:http://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html

1、校驗數字的表達式

 1 數字:^[0-9]*$
 2 n位的數字:^\d{n}$
 3 至少n位的數字:^\d{n,}$
 4 m-n位的數字:^\d{m,n}$
 5 零和非零開頭的數字:^(0|[1-9][0-9]*)$
 6 非零開頭的最多帶兩位小數的數字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
 7 帶1-2位小數的正數或負數:^(\-)?\d+(\.\d{1,2})?$
 8 正數、負數、和小數:^(\-|\+)?\d+(\.\d+)?$
 9 有兩位小數的正實數:^[0-9]+(.[0-9]{2})?$
10 有1~3位小數的正實數:^[0-9]+(.[0-9]{1,3})?$
11 非零的正整數:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
12 非零的負整數:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
13 非負整數:^\d+$ 或 ^[1-9]\d*|0$
14 非正整數:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
15 非負浮點數:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
16 非正浮點數:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
17 正浮點數:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
18 負浮點數:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
19 浮點數:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

2、校驗字符的表達式

 1 漢字:^[\u4e00-\u9fa5]{0,}$
 2 英文和數字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
 3 長度為3-20的所有字符:^.{3,20}$
 4 由26個英文字母組成的字符串:^[A-Za-z]+$
 5 由26個大寫英文字母組成的字符串:^[A-Z]+$
 6 由26個小寫英文字母組成的字符串:^[a-z]+$
 7 由數字和26個英文字母組成的字符串:^[A-Za-z0-9]+$
 8 由數字、26個英文字母或者下划線組成的字符串:^\w+$ 或 ^\w{3,20}$
 9 中文、英文、數字包括下划線:^[\u4E00-\u9FA5A-Za-z0-9_]+$
10 中文、英文、數字但不包括下划線等符號:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
11 可以輸入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
12 禁止輸入含有~的字符:[^~\x22]+

3、特殊需求表達式

 1 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
 2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
 3 InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
 4 手機號碼:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
 5 電話號碼("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 
 6 國內電話號碼(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
 7 身份證號(15位、18位數字):^\d{15}|\d{18}$
 8 短身份證號碼(數字、字母x結尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
 9 帳號是否合法(字母開頭,允許5-16字節,允許字母數字下划線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10 密碼(以字母開頭,長度在6~18之間,只能包含字母、數字和下划線):^[a-zA-Z]\w{5,17}$
11 強密碼(必須包含大小寫字母和數字的組合,不能使用特殊字符,長度在8-10之間):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$  
12 日期格式:^\d{4}-\d{1,2}-\d{1,2}
13 一年的12個月(01~09和1~12):^(0?[1-9]|1[0-2])$
14 一個月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$ 
15 錢的輸入格式:
16    1.有四種錢的表示形式我們可以接受:"10000.00" 和 "10,000.00", 和沒有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$ 
17    2.這表示任意一個不以0開頭的數字,但是,這也意味着一個字符"0"不通過,所以我們采用下面的形式:^(0|[1-9][0-9]*)$ 
18    3.一個0或者一個不以0開頭的數字.我們還可以允許開頭有一個負號:^(0|-?[1-9][0-9]*)$ 
19    4.這表示一個0或者一個可能為負的開頭不為0的數字.讓用戶以0開頭好了.把負號的也去掉,因為錢總不能是負的吧.下面我們要加的是說明可能的小數部分:^[0-9]+(.[0-9]+)?$ 
20    5.必須說明的是,小數點后面至少應該有1位數,所以"10."是不通過的,但是 "10" 和 "10.2" 是通過的:^[0-9]+(.[0-9]{2})?$ 
21    6.這樣我們規定小數點后面必須有兩位,如果你認為太苛刻了,可以這樣:^[0-9]+(.[0-9]{1,2})?$ 
22    7.這樣就允許用戶只寫一位小數.下面我們該考慮數字中的逗號了,我們可以這樣:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ 
23    8.1到3個數字,后面跟着任意個 逗號+3個數字,逗號成為可選,而不是必須:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$ 
24    備注:這就是最終結果了,別忘了"+"可以用"*"替代如果你覺得空字符串也可以接受的話(奇怪,為什么?)最后,別忘了在用函數時去掉去掉那個反斜杠,一般的錯誤都在這里
25 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
26 中文字符的正則表達式:[\u4e00-\u9fa5]
27 雙字節字符:[^\x00-\xff]    (包括漢字在內,可以用來計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1))
28 空白行的正則表達式:\n\s*\r (可以用來刪除空白行) 29 HTML標記的正則表達式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (網上流傳的版本太糟糕,上面這個也僅僅能部分,對於復雜的嵌套標記依舊無能為力)
30 首尾空白字符的正則表達式:^\s*|\s*$或(^\s*)|(\s*$) (可以用來刪除行首行尾的空白字符(包括空格、制表符、換頁符等等),非常有用的表達式) 31 騰訊QQ號:[1-9][0-9]{4,} (騰訊QQ號從10000開始) 32 中國郵政編碼:[1-9]\d{5}(?!\d) (中國郵政編碼為6位數字) 33 IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址時有用)
34 IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))   

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM