常用常新:正则表达式在Java中的基本使用
一 概念
正则表达式是对字符串操作的一种逻辑公式,就是用普通字符和有特殊意义的特殊字符两种的组合,组成一个“规则字符串“,这个“规则字符串”用来表达对字符串的一种过滤逻辑。说白了正则是用来专门处理字符串的工具,日常操作字符串要时时刻刻想到它。
二 用途
-
匹配判断:给定的字符串是否符合正则的过滤逻辑,例如我们最常用的手机、邮箱等的校验;
-
获取处理:可以通过正则,从字符串中获取我们想要的特定部分,并进行操作处理,例如字符串提取、分割、模板替换等;
三 字符种类
既然正则是由字符串组成,那首先要识别它的组成部分,知道每个字符代表什么意思。这里简单分下类。
3.1 普通字符
1-9 a-z A-Z _ - @ & } ]等,数字、大小写字母、还有一些字符在正则中代表其本身。也就是1就是1,@就是@,没有什么特殊含义。
3.1 特殊字符
^ $ | . * + ? \ ( ) { [ 等,某些特殊字符在正则中具有特殊含义,具有特定的功能。例如.用来表示任意的一个字符。此时若想使用使用特殊字符其本身,可使用转义字符\,例如.要写作\.,|要写作\|。
这里值得注意的是小括号
( )前后都是特殊字符,中括号和大括号前一半[ {是特殊字符,后一半] }则是普通字符。
3.1 组合字符
\d \w 等,这种特定字符通过多个字符组合而成,也表示一种特殊含义,如\d代表数字。
四 反斜杠数量问题
在Java日常使用中一直被反斜杠\的数量问题搞的懵逼,时有时没有,一会两个、一会又四个。懵逼的主要原因有二:
一 、搞不清或搞混了字符含义,尤其认识不到哪些字符在正则中是特殊字符需要转义。
二 、在Java中\也是特殊符号(转义字符),想要表示其原义就要多使用一个\转义。 所以\在Java中表示原义就要写成\\。
理清楚这两个原因,数量问题也就不难搞懂了。例如在Java中正则里的一个\居然需要四个写作\\\\。
Java中要表示一个反斜杠符号本身就要转义一次,写作
\\,又因为\在正则中本身也是特殊字符,需要转义,两个反斜杠再各转一次就变成四个了。
String s="123abc_123_2132";
String s1="123abc|123|2132";
String s2="123abc1232132";
String s3="123|abc.123%2132";
String s4="123\\abc\\123\\2132";
// _替换为@
System.out.println( s.replaceAll("_","@"));
// |替换为@
System.out.println( s1.replaceAll("\\|","@"));
// 所有数字都替换为@
System.out.println( s2.replaceAll("\\d","@"));
// 将・ | % 都替换为@
System.out.println( s3.replaceAll("[\\|\\.%]","@"));
// 反斜杠替换
System.out.println( s4.replaceAll("\\\\","@"));
-------------------------------------------------------------
123abc@123@2132
123abc@123@2132
@@@abc@@@@@@@
123@abc@123@2132
123@abc@123@2132
五 一般匹配
5.1 单字符匹配
| 字符 | 含义 |
|---|---|
| ^ | 正则字符开头 |
| $ | 正则字符结尾 |
| . | 任意的一个字符 |
| \d | 数字 |
| \D | 非数字 |
| \w | 字符、数字、下划线 |
| \W | 非(字符、数字、下划线) |
| \s | 空格和tab字符(\t) |
| \S | 非空格和tab字符(\t) |
| \n | 换行符 |
| \r | 回车符 |
| \u548c | 指定Unicode字符 |
5.2 字符集匹配(范围匹配)
| 字符 | 含义 |
|---|---|
| [] | 匹配方括号中定义的字符集之一 |
| [^] | 字符集否定匹配,匹配没有在方括号中定义的字符 |
| [a-zA-Z] | 只匹配字母 |
| [1-8] | 只匹配1到8的数字 |
| [abc] | 只匹配a或b或c中一个 |
5.3 多次匹配(重复匹配)
单字符匹配和字符集匹配都只能匹配到一个字符,可结合多次匹配以达到匹配字符串的目的。
| 字符 | 含义 |
|---|---|
| * | 0到n次匹配 |
| ? | 0到1次匹配 |
| + | 1到n次匹配 |
| {n,} | 匹配n次以上 |
| {n,m} | 匹配n到m次 |
5.4 或匹配
多个正则之间|隔开。弥补字符集匹配只能针对字符的缺点。
| 字符 | 含义 |
|---|---|
| java|python | 子表达式中可以使用单字符和字符集 |
String s2="python_js_java_go";
System.out.println(s2.replaceAll("java|js","nb"));
---------------------------------------------
python_nb_nb_go
5.5 子段匹配
一长串正则表达式中一部分作为一个独立的子正则,使用
()定义子表达式。
| 字符 | 含义 |
|---|---|
| ([abc]\d+) | 子表达式中可以使用单字符和字符集 |
| (){1,2} | 子表达式也可以结合次数规则 |
5.6 综合练习
这里练习一个判断字符串是否是数字(包含整数、小数)的正则。
-
写一个判断是否是整数的
[0-9]+,表示数字至少出现1次; -
如果后面是小数的话则有小数点,加上
\\.?,小数点可有可无且需要转义,此时
变为[0-9]+\\.?;
-
小数点后面数字同样为
[0-9]+此时变为[0-9]+\\.?[0-9]+ -
负数需要加上负号
-?变为-?[0-9]+\.?[0-9]+ -
此时还差一步,字符为0时判断错误。
-
如何解决?把小数点及后面数字当作一个子正则,整数无,小数有。此时正则变为
-?[0-9]+(\\.?[0-9]+)? -
补上正则开始结束符号最终为
^-?[0-9]+(\\.?[0-9]+)?$
六 基本使用场景
-
最常用的使用Pattern和Matcher对象来进行判断操作
-
String对象的spilt和replaceAll方法也可直接使用正则
// 判断是否是数字
Pattern pattern = Pattern.compile("^-?[0-9]+(\\.?[0-9]+)?$");
System.out.println(pattern.matcher("123").matches());// true
System.out.println(pattern.matcher("-212").matches());// true
System.out.println(pattern.matcher("12.1234").matches());// true
System.out.println(pattern.matcher("-46.1234").matches());// true
System.out.println(pattern.matcher("0").matches());// true