匹配规则
若正则表达式内有特殊字符,那就需要用\
转义,正则表达式a\&c
,其中\&
是用来匹配特殊字符&
的,它能精确匹配字符串"a&c"
。在Java中对应正则表达式a\&c
的字符串为a\\&c
。两个\\
实际上表示的是一个\
若想匹配非ASCLL字符,例如匹配中文,那就用\u####的十六进制表示,例如\u548c
的Unicode编码是和
,则a\u548cc
匹配字符串”a和c”
精准匹配不常用正则表达式,一般用String.equals()就可以做到。大多数情况下,正则表达式往往用于模糊匹配
匹配任意字符
例如,正则表达式a.c
中间的.
可以匹配任意一个字符。
匹配数字
用.
可以匹配任意字符,如果只想匹配0~9这样的单个数字,可以用\d匹配 。
匹配常用字符
用\w
可以 匹配一个字母、数字或下划线
匹配空格字符
用\s
可以匹配一个空格字符,注意空格字符不但包含空格,还包括tab字符
匹配非数字
用\D
匹配一个非数字
以此类推,\W
可以匹配\w
不能匹配的字符,\S
可以匹配\s
不能匹配的字符
重复匹配
若要匹配多个数字,比如“A380”,则可以使用修饰符*
,它可以匹配任意个字符,包括0个字符
修饰符+
表示可以匹配至少一个字符
修饰符?
表示可以匹配0个或1个字符,无法匹配超过一个的字符
若要精准匹配指定的n个字符,则可以用修饰符{n}
若要精准匹配指定的n个到m个字符,则可以用修饰符{n,m}
小结
单个字符的匹配规则如下:
| 正则表达式 | 规则 | 可以匹配 | | —- | —- | —- |
|
A
| 指定字符
| A
|
|
\u548c
| 指定Unicode字符
| 和
|
|
.
| 任意字符
| a
,b
,&
,0
|
|
\d
| 数字0~9
| 0
~9
|
|
\w
| 大小写字母,数字和下划线
| a``Z
,0
~9
,_
|
|
\s
| 空格、Tab键
| 空格,Tab
|
|
\D
| 非数字
| a
,A
,&
,_
,……
|
|
\W
| 非\w
| &
,@
,中
,……
|
|
\S
| 非\s
| a
,A
,&
,_
,……
|
多个字符的匹配规则如下:
| 正则表达式 | 规则 | 可以匹配 | | —- | —- | —- |
|
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{0,3}
| 最多n个字符
| 空,A
,AA
,AAA
|
匹配开头和结尾
用正则表达式中,用^表示开头,用$表示结尾。
匹配指定范围
使用[…]可以匹配范围内的字符,、[123456789]可以匹配1~9,把所有字符列出来太麻烦,可以把[123456789]写成[1-9]
同理,[a-zA-F]可以匹配所有大小写英文字符。
[…]的用法还可以排除,即不包含指定范围的字符。例如我们要匹配任意非数字的字符,可以写成[^1-9]
或匹配原则
用|
连接的两个正则规则是或规则,例如,AB|CD
表示可以匹配AB
或CD
。
使用括号
现在我们想要匹配字符串learn java
、learn php
和learn go
怎么办?一个最简单的规则是learn\sjava|learn\sphp|learn\sgo
,但是这个规则太复杂了,可以把公共部分提出来,然后用(...)
把子规则括起来表示成learn\\s(java|php|go)
。
小结
复杂匹配规则主要有:
| 正则表达式 | 规则 | 可以匹配 | | —- | —- | —- |
| ^ | 开头 | 字符串开头 |
| $ | 结尾 | 字符串结束 |
| [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
|
分组匹配
(…)还有一个作用就是分组匹配,对于用正则匹配区号-电话号
这个规则,示例为\d{3,4}\t\d{6,8}
,在匹配成功后下一步是提取区号和电话号,分别存入数据库,正确的做法就是用(...)
将刚才的正则表达式变为(\d{3,4}\t\d{6,8})
。如果匹配成功,就可以直接从Matcher.group(index)
返回子串。注意如果传入的参数为1表示第一个子串,2为第二个子串,0表示整个匹配到的字符串。
非贪婪匹配原则
正则表达默认的模式为贪婪匹配原则,例如对于"123000"
这个字符串,我们期望得到末尾零的个数,故写出正则表达式(\d+)(0*)
,但实际上的结果为
贪婪匹配即它总是尽可能地往后匹配,要使后面的0*
尽可能的多匹配,就必须让\d+
使用非贪婪匹配。在规则\d+
后面加上?
号即表示非贪婪匹配,注意要将\d??
和\d?
区分开,在\d??
中,第一个问好表示匹配0个或1个数字,对第二个?表示非贪婪匹配。对于字符串”9999”,使用(\d??)(9*)
匹配,结果两个子串为""
和9999""
,非贪婪表示尽可能少的匹配,结果匹配了0个9
分割、搜索和替换
- 分割使用
String.split("\\s");
`` "a b c".split("\\s");// 结果{"a","b","c"}
,\ “a b c”.split(“\s”); // { “a”, “b”, “”, “c” } “a, b ;; c”.split(“[\,\;\s]+”); // { “a”, “b”, “c” }
2. 搜索字符串
String s = "the quick brown fox jumps over the lazy dog.";
Pattern p = Pattern.compile("\\wo\\w");
Matcher m = p.matcher(s);
while (m.find()) {
String sub = s.substring(m.start(), m.end());
System.out.println(sub);
}
// result: // row // fox // dog
3. 替换字符串
String s = "The quick\t\t brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s+", " ");
System.out.println(r); // "The quick brown fox jumps over the lazy dog."
4. 反向引用
如果要将匹配到的子串进行处理,比如前后加一个`<b>xxxx</b>`,则可以使用$1,$2来反向引用匹配到的子串
String s = "the quick brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s([a-z]{4})\\s", " <b>$1</b> ");
System.out.println(r);
``
结果:
the quick brown fox jumps over the lazy dog.`