正则表达式常用语法
单个字符的匹配规则
| 正则表达式 | 规则 | 可以匹配 |
|---|---|---|
A |
固定字符 | A |
\\u548c |
指定unicode字符 | 和 |
. |
任意字符 | a,1,-,&,*,# |
\\d |
数字0-9 | 0-9 |
\\w |
大小写字母、数字和下划线 | 0-9,a-z,A-Z,_ |
\\s |
空格、Tab键 | 空格,Tab |
\\D |
任意一个非数字字符 | |
\\W |
非\w | |
\\S |
非\s |
多个字符的匹配规则
| 正则表达式 | 规则 | 可以匹配 |
|---|---|---|
A* |
任意个数字符 | 空,A,AA,AAA,…… |
A+ |
至少 1 个字符 | A,AA,AAA,…… |
A? |
0 个或 1 个字符 | 空,A |
A{3} |
指定个数字符 | AAA |
A{2,3} |
指定范围个数字符 | AA,AAA |
A{2,} |
至少 n 个字符 | AA,AAA,AAAA,…… |
A{,3} |
最多 n 个字符 | 空,A,AA,AAA |
复杂匹配规则
| 正则表达式 | 规则 | 可以匹配 |
|---|---|---|
^ |
开头 | 字符串开头 |
$ |
结尾 | 字符串结束 |
[ABC] |
[…] 内任意字符 | A,B,C |
[A-F0-9xy] |
指定范围的字符 | A-F,0-9,x,y |
[^A-F] |
指定范围外的任意字符 | 非A~F |
AB|CD|EF |
AB 或 CD 或 EF |
AB,CD,EF |
[a-g&&[^b-d]] |
代表a-g字符并且不是b-d | a,e,f,g |
非贪婪匹配
在介绍非贪婪匹配前,我们先看一个简单的问题:
给定一个字符串表示的数字,判断该数字末尾0的个数。例如:
"123000":3 个0"10100":2 个0"1001":0 个0
可以很容易地写出该正则表达式:(\d+)(0*)
public class Main {public static void main(String[] args) {Pattern pattern = Pattern.compile("(\\d+)(0*)");Matcher matcher = pattern.matcher("1230000");if (matcher.matches()) {System.out.println("group1=" + matcher.group(1)); // "1230000"System.out.println("group2=" + matcher.group(2)); // ""}}}
然而打印的第二个子串是空字符串""。
实际上,我们期望分组匹配结果是:
| input | \\d+ |
0* |
|---|---|---|
| 123000 | “123” | “000” |
| 10100 | “101” | “00” |
| 1001 | “1001” | “” |
但实际的分组匹配结果是这样的:
| input | \\d+ |
0* |
|---|---|---|
| 123000 | “123000” | “” |
| 10100 | “10100” | “” |
| 1001 | “1001” | “” |
仔细观察上述实际匹配结果,实际上它是完全合理的,因为\d+确实可以匹配后面任意个0。
这是因为正则表达式默认使用贪婪匹配:任何一个规则,它总是尽可能多地向后匹配,因此,\d+总是会把后面的0包含进来。
要让\d+尽量少匹配,让0*尽量多匹配,我们就必须让\d+使用非贪婪匹配。在规则\d+后面加个?即可表示非贪婪匹配。我们改写正则表达式如下:
public class Main {public static void main(String[] args) {Pattern pattern = Pattern.compile("(\\d+?)(0*)");Matcher matcher = pattern.matcher("1230000");if (matcher.matches()) {System.out.println("group1=" + matcher.group(1)); // "123"System.out.println("group2=" + matcher.group(2)); // "0000"}}}
因此,给定一个匹配规则,加上?后就变成了非贪婪匹配。
我们再来看这个正则表达式(\d??)(9*),注意\d?表示匹配 0 个或 1 个数字,后面第二个?表示非贪婪匹配,因此,给定字符串"9999",匹配到的两个子串分别是""和"9999",因为对于\d?来说,可以匹配 1 个9,也可以匹配 0 个9,但是因为后面的?表示非贪婪匹配,它就会尽可能少的匹配,结果是匹配了 0 个9。
