Java(API)——正则表达式
一,正则表达式的入门
正则表达式是,并用来匹配字符串。
例如,判断手机号,我们用正则表达式\d{11}
boolean isValidMobileNumber( String s){
return s.matches("\\d{11}");
}
- s是你想检验的String
- 正则表达式里面有一个方法.matches(正则表达式)
- 正则表达式是以字符串的形式显示
- java的\\d等同于\d,第一个\是转义符,表示整数
- {11},表示有11个整数
eg:
要判断用户输入的年份是否是20##
年,我们先写出规则如下:
一共有4个字符,分别是:2
,0
,0~9任意数字
,0~9任意数字
。
对应的正则表达式就是:20\d\d
,其中\d
表示任意一个数字。
把正则表达式转换为Java字符串就变成了20\\d\\d
,注意Java字符串用\\
表示\
。
public class Test {public static void main(String[] args) {String s = "20\\d\\d";System.out.println("2019".matches(s)); //trueSystem.out.println("2123".matches(s)); //false}
}
- 正则表达式是字符串的形式表达出来的
- str.matches(s) 返回的是boolean
二,正则表达式的匹配规则
1.匹配规则
- 正则表达式的匹配规则是从左到右按规则匹配
- 正则表达式有特殊字符,那就需要用
\
转义,比如正则表达式a\&c
,其中\&
是用来匹配特殊字符&
的,它能精确匹配字符串"a&c"
,但不能匹配"ac"
、"a-c"
、"a&&c"
- 两个
\\
实际上表示的是一个\
1)匹配非ASCII字符
如果想匹配非ASCII字符,例如中文,那就用\u####
的十六进制表示,例如:a\u6216c
匹配字符串"a或c",说明或的Unicode编码为6216
2)匹配任意字符
.
可以匹配一个任意字符
3)匹配数字
/d匹配数字,仅限单个数字字符
4)匹配常用字符
用\w
可以匹配一个字母、数字或下划线,w的意思是word
java\w
可以匹配:"javac"
,"java9"
,"java_"
5)匹配空格字符
用\s
可以匹配一个空格字符,注意空格字符包括空格,还包括tab字符(在Java中用\t
表示)。
例如,a\sc
可以匹配:
"a c"
,因为\s
可以匹配空格字符;
"a c"
,因为\s
可以匹配tab字符\t
。
它不能匹配"ac"
,"abc"
等。
6)匹配非数字
\D
则匹配一个非数字。例如,00\D
可以匹配:
"00A"
,因为\D
可以匹配非数字字符A
;
"00#"
,因为\D
可以匹配非数字字符#
。
public class Test {public static void main(String[] args) {String s = "java\\d"; //对应正则表达式java\dSystem.out.println("java9".matches(s));//trueSystem.out.println("java10".matches(s));//falseSystem.out.println("javac".matches(s));//false}
}
注意:10是两个数字1和0组成的哦
7)重复匹配
1,修饰符*
可以匹配任意个字符,包括0个字符。我们用A\d*
可以匹配:
A
:因为\d*
可以匹配0个数字;A0
:因为\d*
可以匹配1个数字0
;A380
:因为\d*
可以匹配多个数字380
。
2,修饰符+
可以匹配至少一个字符。我们用A\d+
可以匹配:
A0
:因为\d+
可以匹配1个数字0
;A380
:因为\d+
可以匹配多个数字380
。- 但它无法匹配
"A"
,因为修饰符+
要求至少一个字符。
3,修饰符?
可以匹配0个或一个字符。我们用A\d?
可以匹配:
A
:因为\d?
可以匹配0个数字;A0
:因为\d?
可以匹配1个数字0
。- 但它无法匹配
"A33"
,因为修饰符?
超过1个字符就不能匹配了。
4,想精确指定n个字符,用修饰符{n}
就可以。A\d{3}
可以精确匹配:
A380
:因为\d{3}
可以匹配3个数字380
。
5,想指定匹配n~m个字符,用修饰符{n,m}
就可以。A\d{3,5}
可以精确匹配:
A380
:因为\d{3,5}
可以匹配3个数字380
;A3800
:因为\d{3,5}
可以匹配4个数字3800
;A38000
:因为\d{3,5}
可以匹配5个数字38000;
- 如果没有上限,那么修饰符
{n,}
就可以匹配至少n个字符。
电话匹配练习:
请编写一个正则表达式匹配国内的电话号码规则:3~4位区号加7~8位电话,中间用-
连接,例如:010-12345678
。
进阶:国内区号必须以0开头,而电话号码不能以0开头,试修改正则表达式,使之能更精确地匹配。
public class Test {public static void main(String[] args) {//TO DO YOUR CODEString re = "0\\d{2,3}-\\d{7,8}";//...........for (String s : List.of("010-12345678", "020-9999999", "0755-7654321")) {if (!s.matches(re)) {System.out.println("测试失败: " + s);return;}}for (String s : List.of("010 12345678", "A20-9999999", "0755-7654.321")) {if (s.matches(re)) {System.out.println("测试失败: " + s);return;}}System.out.println("测试成功!");}
}
2.小结
单个字符的匹配规则如下:
正则表达式 | 规则 | 可以匹配 |
---|---|---|
A | 指定字符(很少用),equals()就能解决 | A |
\u548c | 指定Unicode字符,十六进制 | 和 |
. | 任意字符 | a ,b ,& ,0 |
\d | 数字0~9 | 0 ~9 |
\w | 大小写字母,数字和下划线 | a ~z ,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 |
三,复杂匹配规则
1.匹配开头和结尾
进行多行匹配时,我们用^
表示开头,$
表示结尾
例如,^A\d{3}$
,可以匹配"A001"
、"A380"
。
2.匹配指定范围
如果我们规定一个7~8位数字的电话号码不能以0
开头
\d{7,8}
是不行的,因为第一个\d
可以匹配到0
使用[...]
可以匹配范围内的字符,例如,[123456789]
可以匹配1
~9
,所以答案:
[123456789]\d{6,7}
。
[...]
还有一种写法,直接写[1-9]
就可以,所有答案:[1-9]\d{6,7} //解释:第一位是1-9的不为零的数字,\d表示后面输入整数,6到7位的整数
匹配大小写不限的十六进制数,比如1A2b3c
,我们可以这样写:[0-9a-fA-F]
,它表示一共可以匹配以下任意范围的字符:
0-9
:字符0
~9
;a-f
:字符a
~f
;A-F
:字符A
~F
。
要匹配6位十六进制数,{n}
可以继续配合使用:[0-9a-fA-F]{6}
。类型+位数
[...]
还有一种排除法,即不包含指定范围的字符。假设我们要匹配任意字符,但不包括数字,可以写[^1-9]{3}
:
- 可以匹配
"ABC"
,因为不包含字符1
~9
; - 可以匹配
"A00"
,因为不包含字符1
~9
; - 不能匹配
"A01"
,因为包含字符1
; - 不能匹配
"A05"
,因为包含字符5
。
3.或规则匹配
用|
连接的两个正则规则是或规则,例如,AB|CD
表示可以匹配AB
或CD
。
public class Test {public static void main(String[] args) {String re = "java|php";System.out.println("java".matches(re));//trueSystem.out.println("php".matches(re));//trueSystem.out.println("go".matches(re));//false}
}
如果想加上go,改写成java|php|go。
4.使用括号
- 匹配字符串
learn java
、learn php
和learn go
- 一个最简单的规则是
learn\sjava|learn\sphp|learn\sgo
- 可以把公共部分提出来,然后用
(...)
把子规则括起来表示成learn\\s(java|php|go)
。
public class Test {public static void main(String[] args) {String re = "learn\\s(java|php|go)";System.out.println("learn java".matches(re));//trueSystem.out.println("learn php".matches(re));//trueSystem.out.println("learn go".matches(re));//true}
}
5.小结
复杂匹配规则主要有:
正则表达式 | 规则 | 可以匹配 |
---|---|---|
^ | 开头 | 字符串开头 |
$ | 结尾 | 字符串结束 |
[ABC] | […]内任意字符 | A,B,C |
[A-F0-9x-y] | 指定范围的字符 | A ,……,F ,0 ,……,9 ,x ,y |
[^A-F] | 指定范围外的任意字符 | 非A ~F |
AB|CD|EF | AB或CD或EF | AB ,CD ,EF |
四,非贪婪匹配
\d+0*可以匹配1234500000
而其中的\d+(表示至少匹配一个数字)可以匹配到“1234500000”
而0*匹配到的是“”
这就是因为正则表达式默认使用贪婪匹配:任何一个规则,它总是尽可能多地向后匹配,因此,\d+
总是会把后面的0
包含进来。
要让\d+
尽量少匹配,让0*
尽量多匹配,我们就必须让\d+
使用非贪婪匹配。在规则\d+
后面加个?
即可表示非贪婪匹配