標籤:pre ever compile 聲明 線程 find efi 相同 目標
概述
Regex是一個強大的字串處理工具,可以實現對字串的尋找、提取、分割、替換等操作。
String類的幾個方法需要依賴Regex的支援。
| 方法 |
方法說明 |
| boolean matches(String regex) |
判斷該字串是否匹配指定的Regex |
| String replaceAll(String regex,String replacement) |
將該字串中所有匹配regex的子字串替換成replacement |
| String replaceFirst(String regex,String replacement) |
將該字串中第一個匹配regex的子字串替換成replacement |
| String[] split(String regex) |
以regex作為分隔字元,把該字串分割成多個子字串 |
Java提供了Pattern和Matcher類支援Regex。
建立Regex
Regex文法構成
字元 |
說明 |
\ |
將下一字元標記為特殊字元、文本、反向引用或八進位轉義符。例如,"n"匹配字元"n"。"\n"匹配分行符號。序列"\\\\"匹配"\\","\\("匹配"("。 |
^ |
匹配輸入字串開始的位置。如果設定了 RegExp 對象的 Multiline 屬性,^ 還會與"\n"或"\r"之後的位置匹配。 |
$ |
匹配輸入字串結尾的位置。如果設定了 RegExp 對象的 Multiline 屬性,$ 還會與"\n"或"\r"之前的位置匹配。 |
* |
零次或多次匹配前面的字元或子運算式。例如,zo* 匹配"z"和"zoo"。* 等效於 {0,}。 |
+ |
一次或多次匹配前面的字元或子運算式。例如,"zo+"與"zo"和"zoo"匹配,但與"z"不匹配。+ 等效於 {1,}。 |
? |
零次或一次匹配前面的字元或子運算式。例如,"do(es)?"匹配"do"或"does"中的"do"。? 等效於 {0,1}。 |
{n} |
n 是非負整數。正好匹配 n 次。例如,"o{2}"與"Bob"中的"o"不匹配,但與"food"中的兩個"o"匹配。 |
{n,} |
n 是非負整數。至少匹配 n 次。例如,"o{2,}"不匹配"Bob"中的"o",而匹配"foooood"中的所有 o。"o{1,}"等效於"o+"。"o{0,}"等效於"o*"。 |
{n,m} |
M 和 n 是非負整數,其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的頭三個 o。‘o{0,1}‘ 等效於 ‘o?‘。注意:您不能將空格插入逗號和數字之間。 |
? |
當此字元緊隨任何其他限定符(*、+、?、{n}、{n,}、{n,m})之後時,匹配模式是"非貪心的"。"非貪心的"模式比對搜尋到的、儘可能短的字串,而預設的"貪心的"模式比對搜尋到的、儘可能長的字串。例如,在字串"oooo"中,"o+?"只匹配單個"o",而"o+"匹配所有"o"。 |
. |
匹配除"\r\n"之外的任何單個字元。若要匹配包括"\r\n"在內的任一字元,請使用諸如"[\s\S]"之類的模式。 |
(pattern) |
匹配 pattern 並捕獲該匹配的子運算式。可以使用 $0…$9 屬性從結果"匹配"集合中檢索捕獲的匹配。若要匹配括弧字元 ( ),請使用"\("或者"\)"。 |
(?:pattern) |
匹配 pattern 但不捕獲該匹配的子運算式,即它是一個非捕獲匹配,不儲存供以後使用的匹配。這對於用"or"字元 (|) 組合模式組件的情況很有用。例如,‘industr(?:y|ies) 是比 ‘industry|industries‘ 更經濟的運算式。 |
(?=pattern) |
執行正向預測先行搜尋的子運算式,該運算式匹配處於匹配 pattern 的字串的起始點的字串。它是一個非捕獲匹配,即不能捕獲供以後使用的匹配。例如,‘Windows (?=95|98|NT|2000)‘ 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。預測先行不佔用字元,即發生匹配後,下一匹配的搜尋緊隨上一匹配之後,而不是在組成預測先行的字元後。 |
(?!pattern) |
執行反向預測先行搜尋的子運算式,該運算式匹配不處於匹配 pattern 的字串的起始點的搜尋字串。它是一個非捕獲匹配,即不能捕獲供以後使用的匹配。例如,‘Windows (?!95|98|NT|2000)‘ 匹配"Windows 3.1"中的 "Windows",但不匹配"Windows 2000"中的"Windows"。預測先行不佔用字元,即發生匹配後,下一匹配的搜尋緊隨上一匹配之後,而不是在組成預測先行的字元後。 |
x|y |
匹配 x 或 y。例如,‘z|food‘ 匹配"z"或"food"。‘(z|f)ood‘ 匹配"zood"或"food"。 |
[xyz] |
字元集。匹配包含的任一字元。例如,"[abc]"匹配"plain"中的"a"。 |
[^xyz] |
反向字元集。匹配未包含的任何字元。例如,"[^abc]"匹配"plain"中"p","l","i","n"。 |
[a-z] |
字元範圍。匹配指定範圍內的任何字元。例如,"[a-z]"匹配"a"到"z"範圍內的任何小寫字母。 |
[^a-z] |
反向範圍字元。匹配不在指定的範圍內的任何字元。例如,"[^a-z]"匹配任何不在"a"到"z"範圍內的任何字元。 |
\b |
匹配一個字邊界,即字與空格間的位置。例如,"er\b"匹配"never"中的"er",但不匹配"verb"中的"er"。 |
\B |
非字邊界匹配。"er\B"匹配"verb"中的"er",但不匹配"never"中的"er"。 |
\cx |
匹配 x 指示的控制字元。例如,\cM 匹配 Control-M 或斷行符號符。x 的值必須在 A-Z 或 a-z 之間。如果不是這樣,則假定 c 就是"c"字元本身。 |
\d |
數字字元匹配。等效於 [0-9]。 |
\D |
非數字字元匹配。等效於 [^0-9]。 |
\f |
換頁符匹配。等效於 \x0c 和 \cL。 |
\n |
分行符號匹配。等效於 \x0a 和 \cJ。 |
\r |
匹配一個斷行符號符。等效於 \x0d 和 \cM。 |
\s |
匹配任何空白字元,包括空格、定位字元、換頁符等。與 [ \f\n\r\t\v] 等效。 |
\S |
匹配任何非空白字元。與 [^ \f\n\r\t\v] 等效。 |
\t |
定位字元匹配。與 \x09 和 \cI 等效。 |
\v |
垂直定位字元匹配。與 \x0b 和 \cK 等效。 |
\w |
匹配任何字類字元,包括底線。與"[A-Za-z0-9_]"等效。 |
\W |
與任何非單詞字元匹配。與"[^A-Za-z0-9_]"等效。 |
\xn |
匹配 n,此處的 n 是一個十六進位轉義碼。十六進位轉義碼必須正好是兩位元長。例如,"\x41"匹配"A"。"\x041"與"\x04"&"1"等效。允許在Regex中使用 ASCII 代碼。 |
\num |
匹配 num,此處的 num 是一個正整數。到捕獲匹配的反向引用。例如,"(.)\1"匹配兩個連續的相同字元。 |
\n |
標識一個八進位轉義碼或反向引用。如果 \n 前面至少有 n 個捕獲子運算式,那麼 n 是反向引用。否則,如果 n 是八位元 (0-7),那麼 n 是八進位轉義碼。 |
\nm |
標識一個八進位轉義碼或反向引用。如果 \nm 前面至少有 nm 個捕獲子運算式,那麼 nm 是反向引用。如果 \nm 前面至少有 n 個捕獲,則 n 是反向引用,後面跟有字元 m。如果兩種前面的情況都不存在,則 \nm 匹配八進位值 nm,其中 n 和 m 是八位元字 (0-7)。 |
\nml |
當 n 是八位元 (0-3),m 和 l 是八位元 (0-7) 時,匹配八進位轉義碼 nml。 |
\un |
匹配 n,其中 n 是以四位十六進位數表示的 Unicode 字元。例如,\u00A9 匹配著作權符號 (?)。 |
數量標識符
如果需要匹配一個郵遞區號,形式如:000-000,使用Regex:\\d\\d\\d-\\d\\d\\d,這種寫法比較繁瑣,可以採用Regex的數量標識符進行簡寫,寫成如下格式:
\\d{3}-\\d{3}
Regex中的數量標識符支援三種模式:
- Greediness(貪婪模式):Regex中的數量表示預設採用貪婪模式。貪婪模式的運算式會一直匹配下去,直到無法匹配為止。
- Reluctant(勉強模式):用問號“?”尾碼表示,他只會匹配最少的字元。也稱為最小匹配模式。
- Possessive(佔有模式):尾碼用加號“+”表示,完全符合。較少使用,不是所有程式設計語言都支援。
三種模式數量標識符:
| 貪婪模式 |
勉強模式 |
佔用模式 |
運算式說明 |
| X? |
X?? |
X?+ |
X運算式出現0次或者1次 |
| X* |
X*? |
X*+ |
X運算式出現0次或者多次 |
| X+ |
X+? |
X++ |
X運算式出現1次或者多次 |
| X{n} |
X{n}? |
X{n}+ |
X表示是出現n次 |
| X{n,} |
X{n,}? |
X{n,}+ |
X運算式最少出現n次 |
| X{n,m} |
X{n,m}? |
X{n,m}+ |
X運算式最少出現n次,最多出現m次 |
在 Greediness 的模式下,會盡量大範圍的匹配,直到匹配了整個內容,這時發現匹配不能成功時,開始回退縮小匹配範圍,直到匹配成功。
範例程式碼:
String test="list<a href=‘http://www.baidu.com‘>百度</a>list";String reg="<.+>";//\\.+表示任何字元出現一次或者多次System.out.println(test.replaceAll(reg, "***"));
說明:我們期望的匹配內容是<a href=‘http://www.baidu.com‘>,但是在貪婪模式下,他會匹配 a href=‘http://www.baidu.com‘>百度</a,結果輸出:
list***list
在 Reluctant 的模式下,只要匹配成功,就不再繼續嘗試匹配更大範圍的內容。
範例程式碼:
String test="list<a href=‘http://www.baidu.com‘>百度</a>list";String reg="<.+?>";//\\.+表示任何字元出現一次或者多次,?表示勉強方式System.out.println(test.replaceAll(reg, "***"));
輸出結果:
list***百度***list
Possessive 模式與 Greediness 有一定的相似性,那就是都盡量匹配最大範圍的內容,直到內容結束,但與 Greediness 不同的是,完全符合不再回退嘗試匹配更小的範圍。
範例程式碼:
String test="list<a href=‘http://www.baidu.com‘>百度</a>list";String reg="<.++>";//\\.+表示任何字元出現一次或者多次,+表示佔有方式System.out.println(test.replaceAll(reg, "***"));
輸出結果:
list<a href=‘http://www.baidu.com‘>百度</a>list
常用Regex
| 規則 |
Regex文法 |
| 一個或多個漢字 |
^[\u0391-\uFFE5]+$ |
| 郵遞區號 |
^[1-9]\d{5}$ |
| QQ號碼 |
^[1-9]\d{4,11}$ |
| 郵箱 |
^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$ |
| 使用者名稱(字母開頭 + 數字/字母/底線) |
^[A-Za-z][A-Za-z1-9_-]+$ |
| 手機號碼 |
^1[3|4|5|8][0-9]\d{8}$ |
| URL |
^((http|https)://)?([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ |
| 18位社會安全號碼 |
^(\d{6})(18|19|20)?(\d{2})([01]\d)([0123]\d)(\d{3})(\d|X|x)?$ |
Regex的使用
Pattern和Matcher類用於處理Regex。處理過程:
- Regex字串被編譯為Pattern對象。
- 使用Pattern對象建立對應的Matcher對象。
- 執行匹配所涉及的狀態保留在Matcher對象中,多個Matcher對象可以共用同一個Pattern對象。
典型應用代碼如下:
//定義Pattern對象:將字串編譯為Pattern對象Pattern p=Pattern.compile("a*b");//使用Pattern對象建立Matcher對象Matcher m=p.matcher("aaaaab");//擷取匹配結果boolean result=m.matches();//輸出匹配結果System.out.println(result);//輸出true
Pattern對象可以多次重複使用。如果某個Regex僅需一次使用,可以使用Pattern類的靜態方法matches()。
範例程式碼如下:
boolean b=Pattern.matches("a*b", "aaaab");System.out.println(b);//輸出true
Pattern對象表示Regex編譯後在記憶體中的表示形式,是不可變類安全執行緒類。
Matcher類提供了以下常用方法:
| 方法 |
說明 |
| find() |
返回目標字串中是否包含與Pattern匹配的子字串。 |
| group() |
返回上一次與Pattern匹配的子字串。 |
| start() |
返回上一次與Pattern匹配的子字串在目標字串中的開始位置。 |
| end() |
返回上一次與Pattern匹配的子字串在目標字串中的結束位置+1。 |
| lookingAt() |
返回目標字串前面部分與Pattern是否匹配。 |
| matches() |
返回整個目標字串與Pattern是否匹配。 |
| reset() |
將現有的Matcher對象應用於一個新的字元序列。 |
樣本1:使用find()方法和group()方法從目標字串中取出特定子字串。(網路爬蟲提取資訊模型)
//定義目標字串String content="我的電話號碼是13800001234,購買Mac電腦的電話號碼13112340001,拯救單身狗172456789078";//定義提取手機號碼的RegexString reg="((13\\d)|(17\\d))\\d{8}";//定義Pattern對象Pattern p=Pattern.compile(reg);//獲得Matcher對象Matcher m=p.matcher(content);//輸出電話號碼while(m.find()) {System.out.println(m.group());}
樣本2:使用find()方法和start()方法、end()方法確定目標字串中特定子字串的位置。
// 定義目標字串String content = "我的電話號碼是13800001234,購買Mac電腦的電話號碼13112340001,拯救單身狗172456789078";// 定義提取手機號碼的RegexString reg = "((13\\d)|(17\\d))\\d{8}";// 定義Pattern對象Pattern p = Pattern.compile(reg);// 獲得Matcher對象Matcher m = p.matcher(content);// 輸出電話號碼while (m.find()) {System.out.println(m.group() + ",該子字串的起始位置:" + m.start() + ",該子字串的結束位置:"+m.end());}
輸出結果:
13800001234,該子字串的起始位置:7,該子字串的結束位置:1813112340001,該子字串的起始位置:31,該子字串的結束位置:4217245678907,該子字串的起始位置:48,該子字串的結束位置:59
樣本3:其他方法的使用。
此外,matches()方法要求整個字串和Pattern完全符合才返回true。
lookingAt()方法只要求字串以Pattern開頭就會返回true。
reset()方法可將現有的Matcher對象應用於新的字串序列。
範例程式碼:
//定義郵箱字串數組String[] mails= {"[email protected]","[email protected]","[email protected]","abc.com"};//郵箱RegexString mailReg="\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";//定義Pattern對象Pattern mp=Pattern.compile(mailReg);//聲明Matcher對象Matcher m=null;for(String mail:mails) {if(m==null) {//如果Matcher對象為空白,則建立m=mp.matcher(mail);}else {m.reset(mail);//如果Matcher對象不為空白,則應用Matcher對象}String result=mail+(m.matches()?"是":"不是")+"一個有效郵箱地址!";System.out.println(result);}
輸出結果:
[email protected]是一個有效郵箱地址![email protected]是一個有效郵箱地址![email protected]是一個有效郵箱地址!abc.com不是一個有效郵箱地址!
JavaSE-31 JavaRegex