正则表达式常用语法

单个字符的匹配规则

正则表达式 规则 可以匹配
A 固定字符 A
\\u548c 指定unicode字符
. 任意字符 a,1,-,&,*,#
\\d 数字0-9 0-9
\\w 大小写字母、数字和下划线 0-9a-zA-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} 指定范围个数字符 AAAAA
A{2,} 至少 n 个字符 AA,AAA,AAAA,……
A{,3} 最多 n 个字符 空,A,AA,AAA

复杂匹配规则

正则表达式 规则 可以匹配
^ 开头 字符串开头
$ 结尾 字符串结束
[ABC] […] 内任意字符 ABC
[A-F0-9xy] 指定范围的字符 A-F,0-9,x,y
[^A-F] 指定范围外的任意字符 A~F
AB|CD|EF ABCDEF 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*)

  1. public class Main {
  2. public static void main(String[] args) {
  3. Pattern pattern = Pattern.compile("(\\d+)(0*)");
  4. Matcher matcher = pattern.matcher("1230000");
  5. if (matcher.matches()) {
  6. System.out.println("group1=" + matcher.group(1)); // "1230000"
  7. System.out.println("group2=" + matcher.group(2)); // ""
  8. }
  9. }
  10. }

然而打印的第二个子串是空字符串""
实际上,我们期望分组匹配结果是:

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+后面加个?即可表示非贪婪匹配。我们改写正则表达式如下:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Pattern pattern = Pattern.compile("(\\d+?)(0*)");
  4. Matcher matcher = pattern.matcher("1230000");
  5. if (matcher.matches()) {
  6. System.out.println("group1=" + matcher.group(1)); // "123"
  7. System.out.println("group2=" + matcher.group(2)); // "0000"
  8. }
  9. }
  10. }

因此,给定一个匹配规则,加上?后就变成了非贪婪匹配。

我们再来看这个正则表达式(\d??)(9*),注意\d?表示匹配 0 个或 1 个数字,后面第二个?表示非贪婪匹配,因此,给定字符串"9999",匹配到的两个子串分别是"""9999",因为对于\d?来说,可以匹配 1 个9,也可以匹配 0 个9,但是因为后面的?表示非贪婪匹配,它就会尽可能少的匹配,结果是匹配了 0 个9