前言
Pattern
Pattern p = Pattern.compile("a*b")
Matcher m = p.matcher("aaaaab")
boolean b = m.matches()
boolean b = Pattern.matches("a*b", "aaaaab")
Matcher
Matcher matcher = pattern.matcher("abcd");
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(\\d+)");
Matcher matcher = pattern.matcher("123a4567b90d");
while (matcher.find()) {
System.out.println(matcher.group(1));
System.out.println("匹配到的字符串開始索引:" + matcher.start());
System.out.println("匹配到的字符串結束索引:" + (matcher.end() - 1));
}
}
123
匹配到的字符串開始索引:0
匹配到的字符串結束索引:2
4567
匹配到的字符串開始索引:4
匹配到的字符串結束索引:7
90
匹配到的字符串開始索引:9
匹配到的字符串結束索引:10
PatternSyntaxException
構造摘要
行結束符
行結束符 是一個或兩個字符的序列,標記輸入字符序列的行結尾。以下代碼被識別爲行結束符:新行(換行)符 ('\n')
後面緊跟新行符的回車符 ("\r\n")
單獨的回車符 ('\r')
下一行字符 ('\u0085')
行分隔符 ('\u2028')
段落分隔符 ('\u2029)
如果指定 UNIX_LINES(?d)標誌,則新行符('\n')是唯一識別的行結束符。
如果指定 DOTALL 標誌,則正則表達式 . 可以與任何字符包括行結束符除外匹配。
默認情況下,正則表達式 ^ 和 $ 忽略行結束符,僅分別與整個輸入序列的開頭和結尾匹配。如果指定MULTILINE標誌,則 ^ 在輸入的開頭和行結束符之後發生匹配,$ 在輸入的結尾和行結束符之前匹配。
邏輯運算
字符
正則表達式 | 描述 | 例子 |
x | x代表的字符 | Pattern.matches("a", "a") |
\\ | 反斜槓字符 | Pattern.matches("\\\\", "\\") |
\0n | 8進制值n,Unicode碼點等於此值的字符(0 <= n <= 7) | Pattern.matches("\\00", (char) 0 + "") |
\0nn | 8進制值nn,Unicode碼點等於此值的字符(0 <= n <= 7) | Pattern.matches("\\061", "1") |
\0mnn | 8進制值mnn,Unicode碼點等於此值的字符(0 <= m <= 3、0 <= n <= 7) | Pattern.matches("\\0377", "ÿ") |
\xhh | 16進制值hh,Unicode碼點等於此值的字符 | Pattern.matches("\\x31", "1") |
\uhhhh | 16進制值hhhh,Unicode碼點等於此值的字符 | Pattern.matches("\\u597D", "好") |
\x{h...h} | 16進制值{h...h},Unicode碼點等於此值的字符,支持輔助平面字符 | Pattern.matches("\\x{597D}", "好") |
\t | 製表符 ('\u0009') | Pattern.matches("\\u0009", "\t") |
\n | 換行符 ('\u000A') | Pattern.matches("\\u000A", "\n") |
\r | 回車符 ('\u000D') | Pattern.matches("\\u000D", "\r") |
\f | 換頁符 ('\u000C') | Pattern.matches("\\u000C", "\f") |
\a | 報警符 ('\u0007') | Pattern.matches("\\u0007", "\a") |
\e | 轉義符 ('\u001B') | Pattern.matches("\\u001B", "\e") |
字符類別
正則表達式 | 描述 | 例子 |
[abc] | a,,b 或c | Pattern.matches("[abc]", "a") |
[^abc] | 除a,,b或c之外的任意字符 | Pattern.matches("[^abc]", "d") |
[a-zA-Z] | a到z或A到Z | Pattern.matches("[a-zA-Z]", "a") |
[a-d[m-p]] | a到d或m到p,相當於[a-dm-p],並集 | Pattern.matches("[a-d[m-p]]", "a") |
[a-z&&[def]] | d、e或f,交集 | Pattern.matches("[a-z&&[def]]", "d") |
[a-z&&[^bc]] | a到z中除了b和c,相當於[ad-z] | Pattern.matches("[a-z&&[^bc]]", "d") |
[a-z&&[^m-p]] | a-z中除了m到p,相當於:[a-lq-z] | Pattern.matches("[a-z&&[^m-p]]", "d") |
預定義字符類別
正則表達式 | 描述 |
. | 任何字符(與行結束符可能匹配也可能不匹配) |
\d | 數字:[0-9] |
\D | 非數字: [^\d] |
\h | 水平空白字符:[ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000] |
\H | 非水平空白字符 |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\v | 垂直空白字符:[\n\x0B\f\r\x85\u2028\u2029] |
\V | 非垂直空白字符 |
\w | 單詞字符:[a-zA-Z_0-9] |
\W | 非單詞字符:[^\w] |
邊界匹配器
正則表達式 | 描述 |
^ | 匹配行的開頭,受多行模式影響 |
$ | 匹配行的結尾,受多行模式影響 |
\b | 單詞邊界 |
\B | 非單詞邊界 |
\B:不是\b的邊界都屬於\B,比如單詞和單詞的邊界,符號和符號的邊界。
這裏的單詞不是\w代表的0-9a-zA-Z_,我猜想應該是w的超集,包括比如漢字、希臘字母、英文字母、數字、下劃線等等,符號可以是中文符號、英文符號、空格、製表符、換行符等等,更具體的包括哪些只能在實踐中測試。參考下面的例子:
public static void main(String[] args) {
String str = "(我(i ——\t_離";
String rex = "\\b";
Pattern pattern = Pattern.compile(rex);
String[] result = pattern.split(str);
for (String string : result) {
System.out.println("分割的字符串:" + "[" + string + "]");
}
}
分割的字符串:[(]
分割的字符串:[我]
分割的字符串:[(]
分割的字符串:[i]
分割的字符串:[ —— ]
分割的字符串:[_離]
public static void main(String[] args) {
String str = "(我(i ——\t_離";
String rex = "\\B";
Pattern pattern = Pattern.compile(rex);
String[] result = pattern.split(str);
for (String string : result) {
System.out.println("分割的字符串:" + "[" + string + "]");
}
}
分割的字符串:[]
分割的字符串:[(我(i ]
分割的字符串:[—]
分割的字符串:[—]
分割的字符串:[ _]
分割的字符串:[離]
轉義
捕獲組
非捕獲組
非捕獲組,它只分組而不捕獲文本,也就不佔用分組編號,普通非捕獲組的語法是(?:X),X是正則表達式構造。數量詞
Greedy
X? X,一次或一次也沒有X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超過 m 次
public static void main(String[] args) {
Pattern p = Pattern.compile(".{3,10}[0-9]");
String s = "abcd1efgh2";
Matcher m = p.matcher(s);
if (m.find())
System.out.println(m.start() + "-" + m.end());
else
System.out.println("沒匹配");
}
輸出:0-10解釋:Greedy是儘量吃入後再吐出。這個表達式 {3,10}吃入最多字符的10個字符:abcd1efgh2。吃入之後後面的[0-9]發現沒有匹配的,吐出最後一個字符看是數字結果匹配。
Reluctant
X?? X,一次或一次也沒有
X*? X,零次或多次
X+? X,一次或多次
X{n}? X,恰好 n 次
X{n,}? X,至少 n 次
X{n,m}? X,至少 n 次,但是不超過 m 次
public static void main(String[] args) {
Pattern p = Pattern.compile(".{3,10}?[0-9]");
String s = "abcd1efgh2";
Matcher m = p.matcher(s);
if (m.find())
System.out.println(m.start() + "-" + m.end());
else
System.out.println("沒匹配");
}
輸出:0-5解釋:對於Reluctant 來說,就是Greedy的一個相反的匹配模式,他從左到有一個一個開始吃入,而不是整個字符串一個一個吐出。這個表達式{3,10}的吞入最少字符的3個字符:abc,吃入之後後面的[0-9]發現沒有匹配的,再吃入1個字符後纔有匹配。
Possessive
X?+ X,一次或一次也沒有
X*+ X,零次或多次
X++ X,一次或多次
X{n}+ X,恰好 n 次
X{n,}+ X,至少 n 次
X{n,m}+ X,至少 n 次,但是不超過 m 次
public static void main(String[] args) {
Pattern p = Pattern.compile(".{3,10}+[0-9]");
String s = "abcd1efgh2";
Matcher m = p.matcher(s);
if (m.find())
System.out.println(m.start() + "-" + m.end());
else
System.out.println("沒匹配");
}
輸出:沒匹配它和greedy類似,也是全部吃入,但是唯一不同的是它不吐出。
先行斷言和後行斷言
先行斷言和後行斷言其實就是預測之後的字符和之前的字符,只有首先符合預測結果,才能繼續匹配,在預測過程中,匹配的位置不會變化,所以被稱爲“零寬”。例如,預測a後面是bc,那麼所有a後面是bc的字符串符合,接着正常匹配,匹配位置依然從a後面開始而不是從c開始。以下4種都屬於特殊結構的非捕獲組。
(?=pattern) 正向先行斷言 :代表字符串中的一個位置,緊接該位置之後的字符序列能夠匹配pattern。
例如:Pattern.matches("a(?=b)bc", "abc")返回true。
(?!pattern) 負向先行斷言 :代表字符串中的一個位置,緊接該位置之後的字符序列不能匹配pattern。
例如:Pattern.matches("a(?!bcd)bc", "abc")返回true,Pattern.matches("a(?!bc)bc", "abc")返回false。
(?<=pattern) 正向後行斷言 :代表字符串中的一個位置,緊接該位置之前的字符序列能夠匹配pattern。
例如:Pattern.matches("a(?<=a)bc", "abc")返回true。
(?<!pattern) 負向後行斷言 :代表字符串中的一個位置,緊接該位置之前的字符序列不能匹配pattern。
例如:Pattern.matches("a(?<!ab)bc", "abc")返回true,Pattern.matches("a(?<!a)bc", "abc")返回false。
開啓關閉特殊標誌
這裏的標誌就是Pattern類裏的區分大小寫、多行模式等。Pattern中大部分標誌可以使用嵌入式字符串,也可以使用Pattern的常量進行設置。嵌入式字符串直接嵌入在正則表達式裏,可以控制開啓和關閉、是否捕獲。標誌前加“-”表示關閉。
(?idmsux-idmsux) :將開啓或者關閉標誌i d m s u x。
(?idmsux-idmsux:X):將開啓或者關閉標誌i d m s u x,僅對X有效,但是X是作爲非捕獲組。
例如:Pattern.matches("(?i)abc(?-i)abc", "aBCabc")返回true,Pattern.matches("(?i)abc(?-i)abc", "aBCaBc")返回false。