做者:小傅哥
博客:https://bugstack.cnhtml
沉澱、分享、成長,讓本身和他人都能有所收穫!😄
1、前言
編程總在實踐中出結果!
java
正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式一般被用來檢索、替換那些符合某個模式(規則)的文本。
正則引擎主要能夠分爲兩大類:一種是DFA,一種是NFA。這兩種引擎都有了好久的歷史(至今二十多年),當中也由這兩種引擎產生了不少變體!因而POSIX的出臺規避了沒必要要變體的繼續產生。這樣一來,主流的正則引擎又分爲3類:1、DFA,2、傳統型NFA,3、POSIX NFA。git
正則也是一種很是有意思的技術,但每每不知道這些符號的編程在實際使用中該如何使用,所以總結了本篇文章,方便全部小夥伴能夠當成一個工具文章使用,方便處理一些須要使用正則的技術內容。程序員
2、規則
1. 經常使用符號
- x 字符 x
- \ 反斜線字符
- \0n 帶有八進制值 0 的字符 n (0 <= n <= 7)
- \0nn 帶有八進制值 0 的字符 nn (0 <= n <= 7)
- \0mnn 帶有八進制值 0 的字符 mnn(0 <= m <= 三、0 <= n <= 7)
- \xhh 帶有十六進制值 0x 的字符 hh
- \uhhhh 帶有十六進制值 0x 的字符 hhhh
- \t 製表符 ('\u0009')
- \n 新行(換行)符 ('\u000A')
- \r 回車符 ('\u000D')
- \f 換頁符 ('\u000C')
- \a 報警 (bell) 符 ('\u0007')
- \e 轉義符 ('\u001B')
2. 字母字符
- [abc] a、b 或 c(簡單類)
- 任何字符,除了 a、b 或 c(否認)
- [a-zA-Z] a 到 z 或 A 到 Z,兩頭的字母包括在內(範圍)
- [a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](並集)
- [a-z&&[def]] d、e 或 f(交集)
- [a-z&&] a 到 z,除了 b 和 c:[ad-z](減去)
- [a-z&&] a 到 z,而非 m 到 p:[a-lq-z](減去)
3. 預約義字符
- . 任何字符(與行結束符可能匹配也可能不匹配)
- \d 數字:[0-9]
- \D 非數字:
- \s 空白字符:[ \t\n\x0B\f\r]
- \S 非空白字符:
- \w 單詞字符:[a-zA-Z_0-9]
- \W 非單詞字符:
4. POSIX 字符
- \p{Lower} 小寫字母字符:[a-z]
- \p{Upper} 大寫字母字符:[A-Z]
- \p{ASCII} 全部 ASCII:[\x00-\x7F]
- \p{Alpha} 字母字符:[\p{Lower}\p{Upper}]
- \p{Digit} 十進制數字:[0-9]
- \p{Alnum} 字母數字字符:[\p{Alpha}\p{Digit}]
- \p{Punct} 標點符號:!"#$%&'()*+,-./:;<=>?@[]^_`{|}~
- \p{Graph} 可見字符:[\p{Alnum}\p{Punct}]
- \p{Print} 可打印字符:[\p{Graph}\x20]
- \p{Blank} 空格或製表符:[ \t]
- \p{Cntrl} 控制字符:[\x00-\x1F\x7F]
- \p{XDigit} 十六進制數字:[0-9a-fA-F]
- \p{Space} 空白字符:[ \t\n\x0B\f\r]
5. Character 類
- \p{javaLowerCase} 等效於 java.lang.Character.isLowerCase()
- \p{javaUpperCase} 等效於 java.lang.Character.isUpperCase()
- \p{javaWhitespace} 等效於 java.lang.Character.isWhitespace()
- \p{javaMirrored} 等效於 java.lang.Character.isMirrored()
6. Unicode 塊和類別的類
- \p{InGreek} Greek 塊(簡單塊)中的字符
- \p{Lu} 大寫字母(簡單類別)
- \p{Sc} 貨幣符號
- \P{InGreek} 全部字符,Greek 塊中的除外(否認)
- [\p{L}&&] 全部字母,大寫字母除外(減去)
7. 邊界匹配器
- ^ 行的開頭
- $ 行的結尾
- \b 單詞邊界
- \B 非單詞邊界
- \A 輸入的開頭
- \G 上一個匹配的結尾
- \Z 輸入的結尾,僅用於最後的結束符(若是有的話)
- \z 輸入的結尾
8. Greedy 數量詞
- X? X,一次或一次也沒有
- X* X,零次或屢次
- X+ X,一次或屢次
- X{n} X,剛好 n 次
- X{n,} X,至少 n 次
- X{n,m} X,至少 n 次,可是不超過 m 次
9. Reluctant 數量詞
- X?? X,一次或一次也沒有
- X*? X,零次或屢次
- X+? X,一次或屢次
- X{n}? X,剛好 n 次
- X{n,}? X,至少 n 次
- X{n,m}? X,至少 n 次,可是不超過 m 次
10. Possessive 數量詞
- X?+ X,一次或一次也沒有
- X*+ X,零次或屢次
- X++ X,一次或屢次
- X{n}+ X,剛好 n 次
- X{n,}+ X,至少 n 次
- X{n,m}+ X,至少 n 次,可是不超過 m 次
11. Logical 運算符
- XY X 後跟 Y
- X|Y X 或 Y
- (X) X,做爲捕獲組
12. Back 引用
13. 引用
- \ Nothing,可是引用如下字符
- \Q Nothing,可是引用全部字符,直到 \E
- \E Nothing,可是結束從 \Q 開始的引用
14. 特殊構造(非捕獲)
- (?:X) X,做爲非捕獲組
- (?idmsux-idmsux) Nothing,可是將匹配標誌i d m s u x on - off
- (?idmsux-idmsux:X) X,做爲帶有給定標誌 i d m s u x on - off 的非捕獲組 (?=X) X,經過零寬度的正 lookahead
- (?!X) X,經過零寬度的負 lookahead
- (?<=X) X,經過零寬度的正 lookbehind
- (?<!X) X,經過零寬度的負 lookbehind
- (?>X) X,做爲獨立的非捕獲組
3、案例
1. 字符匹配
"a".matches(".")
"a".matches("[abc]")
- 結果:true
- 描述:包含 abc 任意一個字符都匹配,默認匹配一次
"a".matches("[^abc]")
- 結果:false
- 描述:任何字符,除了 a、b 或 c(否認)
"A".matches("[a-zA-Z]")
- 結果:true
- 描述:a 到 z 或 A 到 Z,兩頭的字母包括在內(範圍)
"A".matches("[a-z]|[A-Z]")
- 結果:true
- 描述:a 到 z 或 A 到 Z,兩頭的字母包括在內(範圍)
"A".matches("[a-z(A-Z)]")
- 結果:true
- 描述:a-z,A-Z,匹配範圍相同,括號是捕獲組
"R".matches("[A-Z&&(RFG)]")
- 結果:true
- 描述:匹配 A-Z 與 RFG 交集
"a_8".matches("\\w{3}")
- 結果:true
- 描述:\w 單詞字符等同於 [a-zA-Z_0-9],{3} 匹配三次
"\\".matches("\\\\")
"hello sir".matches("h.*")
- 結果:true
- 描述:. 任何字符,* 匹配零次到屢次
"hello sir".matches(".*ir$")
- 結果:true
- 描述:.* 匹配任意字符 ir$ 肯定匹配行的結尾
"hello sir".matches("^h[a-z]{1,3}o\\b.*")
- 結果:true
- 描述:^h 匹配開頭,[a-z]{1,3}o 匹配1到3次的a-z以後匹配字母o,\b 並不匹配這些單詞分隔字符中的任何一個,它只匹配一個位置。匹配的是o後面的位置。
"hellosir".matches("^h[a-z]{1,3}o\\b.*")
- 結果:false
- 描述:o後面跟着s,是字母,不是空格,\b 不能匹配單詞的o的邊界。
" \n".matches("^[\\s&&[^\\n]]*\\n$")
- 結果:true
- 描述:匹配開頭是一個空格
^[\\s&&[^\\n]]
,且不能是換行符,最後必須是換行 \\n$
System.out.println("java".matches("(?i)JAVA"));
- 結果:true
- 描述:(?i)非捕獲組裏面這個表示忽略大小寫
2. 模式匹配
2.1 驗證匹配
Pattern p = Pattern.compile("[a-z]{3,}");
Matcher m = p.matcher("fgha");
System.out.println(m.matches()); // true,匹配字符3次及以上
- 結果:true
- 描述:Pattern 與 Matcher 一塊兒合做 .Matcher 類提供了對正則表達式的分組支持,以及對正則表達式的屢次匹配支持.。單獨用Pattern只能使用 Pattern.matches(String regex,CharSequence input) 一種最基礎最簡單的匹配。
2.2 匹配功能
Pattern p = Pattern.compile("\\d{3,5}");
Matcher m = p.matcher("123-4536-89789-000");
System.out.println(m.matches());
m.reset();// 把吃進去的字符吐出來從新匹配,否通過m2.matches會吃進去字符 下面的匹配就不成功
System.out.println(m.find());
System.out.println(m.start() + "-" + m.end()); // 找到了 就把首位位置打印下(必須找到才能打印)
System.out.println(m.find());
System.out.println(m.start() + "-" + m.end()); // 找到了 就把首位位置打印下(必須找到才能打印)
System.out.println(m.find());
System.out.println(m.start() + "-" + m.end()); // 找到了 就把首位位置打印下(必須找到才能打印)
System.out.println(m.find());
System.out.println(m.lookingAt()); //每次都是才頭上開始找
測試結果正則表達式
false
true
0-3
true
4-8
true
9-14
true
true
- m.matches(),是全量匹配
- m.reset(),把吃進去的字符吐出來從新匹配,否通過m2.matches會吃進去字符 下面的匹配就不成功
- m.find(),查找匹配
- m.start(),匹配到的字符串,開始位置
- m.end(),匹配到的字符串,結束位置
2.3 匹配普通替換
Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher("java_Java_jAva_jAVa_IloveJava");
System.out.println(m.replaceAll("JAVA"));
- 結果:JAVA_JAVA_JAVA_JAVA_IloveJAVA
- 描述:把全部匹配到的小寫字母 java、JavA,都匹配爲大寫
2.4 匹配邏輯替換
Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher("java_Java_jAva_jAVa_IloveJava fdasfas");
StringBuffer sb = new StringBuffer();
int i = 0;
while (m.find()) {
i++;
if (i % 2 == 0) {
m.appendReplacement(sb, "java");
} else {
m.appendReplacement(sb, "JAVA");
}
}
m.appendTail(sb);
System.out.println(sb);
- 結果:JAVA_java_JAVA_java_IloveJAVA fdasfas
- 描述:按照程序邏輯
i % 2
,進行單雙數替換匹配
2.4 分組匹配
Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
Matcher m = p.matcher("123bb_78987dd_090po");
while(m.find()){
System.out.println(m.group(1));
}
2.5 貪婪的匹配與不貪婪匹配
Pattern p = Pattern.compile("(.{3,10}?)[0-9]");
Matcher m = p.matcher("aaaa5dddd8");
while (m.find()) {
System.out.println(m.start() + "-" + m.end());
}
2.6 普通捕獲
Pattern p = Pattern.compile(".{3}");
Matcher m = p.matcher("ab4dd5");
while(m.find()){
System.out.println(m.group());
}
2.7 非捕獲組(?=a)
Pattern p = Pattern.compile(".{3}(?=a)");
Matcher m = p.matcher("ab4add5");
while (m.find()) {
System.out.println("後面不能是a的:" + m.group());
}
- 結果:
後面不能是a的:ab4
- 描述:(?=a)這個是非捕獲組的意思,最後一個是a並且還不把這個a取出來!!(?=a)這個要是寫在前面就不同了
Pattern p = Pattern.compile("(?!a).{3}");
Matcher m = p.matcher("abbsab89");
while (m.find()) {
System.out.println("前面不能是a的:" + m.group());
}
- 結果:前面不能是a的:bbs、前面不能是a的:b89
- 描述:(?!a)前面不能是a的,因此找到整個字符串中 bbs、b89
2.8 去除><號匹配
Pattern p = Pattern.compile("(?!>).+(?=<)");
Matcher m = p.matcher(">小傅哥<");
while (m.find()) {
System.out.println(m.group());
}
- 結果:小傅哥
- 描述:通常能夠匹配網頁中的特殊字符串裏面的內容信息。
2.9 向前引用
Pattern p = Pattern.compile("(\\d\\d)\\1");
Matcher m = p.matcher("1212");
System.out.println(m.matches());
- 結果:true
- 描述:這裏面的1是向前引用,12是第一匹配到的,下一次在匹配出來12和前面相同 因此是true
4、總結
正則中包括了不少的符號、類型、匹配範圍、匹配數量、匹配原則等等,像貪婪、排除、向前引用等等,這些個使用方法其實也不難,只要按照正則的標準就能夠組合出你想要匹配和攔截出來的字符串內容信息。測試
5、系列推薦
- abc
- bc
- m-p
- 0-9
- \s
- \w
- \p{Lu}