文章目录
一、正则表达式语法
正则表达式是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串。其实就是一种规则,用于处理字符串匹配、查找、替换、判断等问题。
正则表达式作用
(1)正则表达式规范了字符串的格式。
(2)正则表达式可以用来搜索、编辑或处理文本。
(3)正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
正则表达式最难的地方在于,如果表达式写错了,不会报错,只是在你写验证的时候会输出"true"或"false"
1.1、正则范围词
字符 | 说明 |
---|---|
[abc] | a、b 或 c(简单类) 中任意一个字符- |
[^abc] | 任何字符,除了 a、b 或 c(否定) 中任意一个字符 |
[a-zA-Z] | a 到 z 或 A 到 Z,两头的字母包括在内(范围) 中任意一个字符 |
[a-d[m-p]] | a 到 d 或 m 到 p:[a-dm-p](并集) 中任意一个字符 |
[a-z&&[def]] | d、e 或 f(交集) 中任意一个字符 |
[a-z&&[^bc]] | a 到 z,除了 b 和 c:[ad-z] ad到z(减去) 中任意一个字符 |
[a-z&&[^m-p]] | a 到 z,而非 m 到 p:[a-lq-z](减去) 中任意一个字符 |
[abc] a、b 或 c(简单类) 中任意一个字符
[ ]代表单个字符,^代表除了…其他都可以, 除了a或b或c,其他字符都可以
[a-zA-Z]
[a-d[m-p]]
1.2、正则预定义字符类
字符 | 说明 |
---|---|
. | 任何字符 "…"代表两个任意字符 "."代表一个任意字符 |
\d | 数字:[0-9] 中任意一个字符 在输出语句中要写成: \d \D… |
\D | 非数字: [^0-9] 中任意一个字符 |
\s | 空白字符:[ \t\n\x0B\f\r] 中任意一个字符 |
\S | 非空白字符:[^\s] 中任意一个字符 |
\w | 单词字符:[a-zA-Z_0-9] 中任意一个字符 |
\W | 非单词字符:[^\w] 中任意一个字符 |
\A | 匹配以字符串开头 |
\Z | 匹配字符串结尾,如果存在换行,只匹配到换行前的结束字符串 |
\n | 匹配换行符 |
\t | 匹配制表符 |
^regex | 必须匹配一行字符串的开头 |
regex$ | 必须匹配一行字符串的结尾 |
*? | 如果 ? 是限定符 * 或 + 或 ? 或 {} 后面的第一个字符,那么表示非贪婪模式(尽可能少的匹配字符),而不是默认的贪婪模式 |
例如:
1.3、数量词
字符 | 说明 |
---|---|
X? | 一次或一次也没有 :括号里面的字符出现次数一次或一次也没有 : 0到1次 |
X* | 零次或多次 |
X+ | 一次到多次 |
X{n} | 恰好 n 次 |
X{n,} | 至少 n 次 |
X{n,m} | 至少 n 次,但是不超过 m 次 |
例如:
1.4、正则分组
捕获组可以通过从左到右计算其开括号来编号。在java正则表达式中,( )是分组的意思,依旧是所谓的捕获组。每一个( )代表着一个group,该组是通过从左至右计算其括号来编号。
例如,在表达式 ((A)(B(C)))
中,存在四个这样的组:
字符 | 说明 |
---|---|
((A)(B(C))) | |
(A) | 一对括号为一组 |
(B(C)) | |
(C) |
例如:
再例如:对于IP地址的匹配,简单的可以写为如下形式
String pattern = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})";
这里有五个group,group(0)、group(1)、group(2)、group(3)、group(4),并且这几个分组的正则表达式都是一样的。我们可以对上述正则表达式进行简化。结果如下:
String pattern = "(\\d{1,3})(\\.(\\d{1,3})){3}";
再如:
拿匹配hello 标签来说,简单的正则可以这样写:
<title>.*</title>
可以看出,上边表达式中有两个title,完全一样,其实可以通过分组简写。表达式如下:
<(title)>.*</\1>
二、常用正则API
匹配: matches();方法
切割:利用split()方法传入正则表达式
替换:可以使用字符串方法replaceAll(String regex,String replacement)
查找:查找需要使用的对象:
1.Pattern(正则对象)
2.Matcher(匹配器对象):
------| 1、find(); 通知匹配器去匹配字符串查找符合规则的字符串。如果能查找到符合规则的字符串,返回true,否则为false
------| 2、group(); 获取符合规则的字串。
2.1、匹配: matches()方法
//匹配: matches();方法
public class Demo05正则表达式的应用01 {
//匹配: matches();方法
public static void main(String[] args) {
String phone = "13678705044";
matchesPhone(phone);
String tel = "020-38325125";
matchesTel(tel);
}
//需求1:编写一个正则表达式匹配手机号 第一位:只能是1开头, 第二位:3 4 5 7 8 号码长度: 11位
public static void matchesPhone(String phone){
String reg = "1[34578]\\d{9}";
System.out.println(phone.matches(reg)?"合法手机号":"非法手机号");
}
//需求2:匹配固定电话:区号 + 主机号码 其中区号:首位是0 长度: 3~4 主机号:首位不能是0, 长度7~8位
public static void matchesTel(String tel){
String reg = "0\\d{2,3}-[1-9]\\d{6,7}";
System.out.println(tel.matches(reg)?"合法固定电话":"非法固定电话");
}
}
结果:
合法手机号
合法固定电话
2.2、切割:split();
切割:利用split()方法传入正则表达式
//切割:利用split()方法传入正则表达式
public class test {
public static void main(String[] args) {
String str = "明 天 放 假";
testSplit(str);
String str2 = "大家家家明天天要玩玩玩玩得得得得得得得得得开心";
testSplit2(str2);
}
//1、按照空格切割
public static void testSplit(String str){
//空格,且出现一次或者多次
String[] datas = str.split(" +");
System.out.println("切割结果:"+ Arrays.toString(datas));
}
//2、根据叠词进行切割
public static void testSplit2(String str){
//(.)代表分组,分组的没目的是为了能复用起来。 ()表示一组,((A))表示两组
String[] datas = str.split("(.)\\1+");
System.out.println(Arrays.toString(datas));
}
}
结果:
切割结果:[明, 天, 放, 假]
[大, 明, 要, , 开心]
2.3、替换:replaceAll();
替换:可以使用字符串方法replaceAll(String regex,String replacement)
//替换:可以使用字符串方法replaceAll(String regex,String replacement)
public class test {
//切割: split();方法
public static void main(String[] args) {
testReplace();
testReplace2();
}
//需求:将网页上的电话号码替换成*(防止打广告案例)
public static void testReplace(){
String str = "如有需要请联系我:13678705044如有需要请联系我:13678705044如有需要请联系我:13678705044如有需要请联系我:13678705044如有需要请联系我:13678705044如有需要请联系我:13678705044";
String reg = "1[34578]\\d{9}";
str = str.replaceAll(reg,"*****");
System.out.println("被替换的内容是:"+str);
}
//替换
public static void testReplace2(){
String str = "我我我要要要要要要要要要做做做项项项项目目";
str = str.replaceAll("(.)\\1+","$1"); //如果需要在replaceAll方法正则的外部引用组内容,那么使用“$组号”
System.out.println("被替换的内容是:"+str);
}
}
结果:
被替换的内容是:如有需要请联系我:*****如有需要请联系我:*****如有需要请联系我:*****如有需要请联系我:*****如有需要请联系我:*****如有需要请联系我:*****
被替换的内容是:我要做项目
2.4、查找
查找:常用用于text文本内容查找
public class test {
//查找:
public static void main(String[] args) {
//找出三个字母组成的单词
String content = "da jia de jia qi wan bi liao hai kai xin ma";
String reg = "[a-zA-Z]{3}";
//先把要字符串的正则编译成Pattern对象
Pattern p = Pattern.compile(reg); //编译正则字符串,创建正则对象
Matcher m = p.matcher(content); //创建匹配器
System.out.println("有符合规则的字符串吗?"+m.find());
System.out.println("获取结果:"+m.group()); //错误方法
//正确方法
while(m.find()){
System.out.println(m.group());
}
}
}
结果:
jia
wan
lia
hai
kai
xin
案例:正则表达模拟网络爬虫抓取邮箱
public class test {
//正则表达模拟网络爬虫抓取邮箱
public static void main(String[] args) {
//邮箱后缀:.com .cn .com.cn .net
String content = "有事没事联系:1122423@163.com 有事没事联系:1122423@qq.com"
+ "有事没事联系:1122423@qq.com.cn 有事没事联系:1122423@qq.net";
String reg = "[a-zA-Z1-9]\\w{5,17}@[a-zA-Z0-9]{2,}(\\.(com|cn|net)){1,2}";
//把字符串的正则编译成正则对象
Pattern p = Pattern.compile(reg);
Matcher m = p.matcher(content);
while(m.find()){
System.out.println(m.group());
}
}
}
三、易错点示例
3.1、Java 中的反斜杠
反斜杠 \ 在 Java 中表示转义字符,这意味着 \ 在 Java 拥有预定义的含义。
这里例举两个特别重要的用法:
在匹配 .
或{
或 [
或(
或 ?
或 $
或 ^
或 *
这些特殊字符时,需要在前面加上 \\
,比如匹配 . 时,Java 中要写为\\.
,但对于正则表达式来说就是 \.
。
在匹配\
时,Java 中要写为 \\\\
,但对于正则表达式来说就是 \\
。
注意:Java 中的正则表达式字符串有两层含义,首先 Java 字符串转义出符合正则表达式语法的字符串,然后再由转义后的正则表达式进行模式匹配。
注意:Java 中的正则表达式字符串有两层含义,首先 Java 字符串转义出符合正则表达式语法的字符串,然后再由转义后的正则表达式进行模式匹配。
3.2、图片后缀匹配
[jpg|png] 代表匹配 j 或 p 或 g 或 p 或 n 或 g 中的任意一个字符。
(jpg|png) 代表匹配 jpg 或 png。
3.3、Java正则常用语法
规则 | 正则表达式语法 |
---|---|
一个或多个汉字 | ^[\u0391-\uFFE5]+$ |
邮政编码 | ^[1-9]\d{5}$ |
QQ号码 | ^[1-9]\d{4,10}$ |
邮箱 | ^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$ |
用户名(字母开头 + 数字/字母/下划线) | ^[A-Za-z][A-Za-z1-9_-]+$ |
手机号码 | ^1[3|4|5|8][0-9]\d{8}$ |
URL | ^((http|https)://)?([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ |
18位身份证号 | ^(\d{6})(18|19|20)?(\d{2})([01]\d)([0123]\d)(\d{3})(\d|X|x)?$ |
中文字符 | [u4e00-u9fa5] |
空白行的正则 | ns*r |
帐号是否合法((字母开头,允许5-16字节,允许字母数字下划线)) | ^[a-zA-Z][a-zA-Z0-9_]{4,15}$ |
国内电话号码,如 0511-4405222 或 021-87888822 | d{3}-d{8}|d{4}-d{7} |
中国邮政编码 | [1-9]d{5}(?!d) |
验证用户密码(以字母开头,长度在6-18之间, 只能包含字符、数字和下划线) | ^[a-zA-Z]w{5,17}$ |
验证是否含有^%&’’,;=?$"等字符 | [^%&'',;=?$x22] |
只能输入汉字 | ^[u4e00-u9fa5],{0,}$ |
金额校验,精确到2位小数。 | ^[0-9]+(.[0-9]{2})?$ |
货币格式:
'123123211312.333333'.replace(/(?=(?!^)(?:\d{3})+(?:\.|$))(\d{3}(\.\d+$)?)/g, ',$1')
结果:
输出 123,123,211,312.333333
推荐两个在线正则工具
JavaScript、Python 等的在线表达式工具:https://regex101.com/
和 https://regexr.com/
Java 在线表达式工具:[http://www.regexplanet.com/advanced/java/index.html]
(http://www.regexplanet.com/advanced/java/index.html)
正则表达式写的好的文章:
https://blog.csdn.net/weixin_37749640/article/details/86635141