一 正则表达式简介
正则表达式(Regular Expressions),是一个特殊的字符串,可以对普通的字符串进行校验检测等工作。正则表达式不是Java特有的,它是一套独立的语法,可以在java,c++,python等语言中使用。
正则表达式,最基本的使用场景是用来做校验,校验一个字符串是否满足预设的规则。在校验的基础 上,又添加了若干个其他的引用场景,例如: 批量的查找、替换、切割...
二 正则表达式语法
2.1 字符串中常用方法
字符串类型中提供了几个与正则表达式相关的方法
序号 |
方法名以及返回值类型 |
解析 |
---|---|---|
|
|
判断this字符串是否匹配正则表达式regex |
|
|
对this使用匹配上正则表达式的子串进行切分成字符串数组 |
|
|
将一个字符串中的所有的满足正则规则部分的字符串,替换成指定的字符串 |
|
将一个字符串中的第一个满足正则规则部分的字符串,替换成指定的字符串 |
2.2 字符集语法
表达式 |
解析 |
---|---|
[] |
表示匹配括号里的任意一个字符。 |
[abc] |
字符集。匹配a 或者 b 或者 c |
[^abc] |
反向字符集。 |
[a-g] |
字符范围。表示匹配所有的小写字母的任意一个。 |
[^a-z] |
反向字符范围。匹配不在指定的范围内的任何字符。例如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符。 |
[A-Za-z] |
表示匹配所有的小写字母和大写字母的任意一个。 |
[a-zA-Z0-9] |
表示匹配所有的小写字母和大写字母和数字的任意一个。 |
[a-z&&[^bc]] |
表示匹配所有的小写字母除了b和c, 只要匹配上就是true. |
\d |
用于匹配数字字符中的任意一个 相当于[0-9] |
\D |
用于匹配非数字字符中的任意一个 相当于[^0-9] |
\w |
匹配单词字符中的任意一个 单词字符就是[a-zA-Z0-9_] |
\W |
用于匹配非单词字符中的任意一个 |
\s |
用于匹配空格,制表符,退格符,换行符等中的任意一个 |
\S |
用于匹配非空格,制表符,退格符,换行符等中的任意一个 |
. |
用于匹配任意一个字符 |
2.3 量词语法
X? |
匹配0个或1个 |
X* |
匹配0个或1个以上 |
x+ |
匹配1个以上 |
X{n} |
匹配n个 |
X{m,} |
匹配m个以上 |
X{m,n} |
匹配m~n个 |
2.4 分组语法
() |
在正则表达式上可以使用()来进行对一些字符分组,并可以使用逻辑运算符|来进行选择匹配 |
reg: String regex = "(135|137)[\\d]{8}" //匹配手机号是135或者是137开头的
2.5 ^和$
^ |
表示严格从头匹配 |
$ |
表示匹配到结尾 |
三 Pattern的简介
其实,Pattern这个类,才是真正来操作正则表达式的类,它位于java.util.regex包下。在String类中的提供的 matches 、split 、replace等方 法,其实都是对这个类中的某些方法的封装。
在我们调用String类中的提供的 matches 、split 、replace等方法时,底层就会创建一个Pattern对象。这样的做法效率是很低的。我们何不主动创建一个pattern,然后每次需要匹配就直接用它而不需要再次创建,大大提高了程序的效率。
常用方法如下:
static Pattern complie(String regex)
Pattern类的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(String regex)简单工厂方法创建一个正则表达式,
如: Pattern p=Pattern.compile("\\w+");
pattern()
返回正则表达式的字符串形式,其实就是返回Pattern.complile(String regex)的regex参数
Pattern p=Pattern.compile("\\w+");
String regex = p.pattern();//返回 \w+
matcher(String str)
返回一个Matcher类型的对象。
Matcher matcher = p.matcher("michael");
四 Matcher类
Pattern类只能做一些简单的匹配操作,要想得到更强更便捷的正则匹配操作,那就需要将Pattern与Matcher一起合作.Matcher类提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持。简单来说,Matcher对象就是Pattern对象与字符串匹配的一个结果。
4.1 Matcher对象的获取
Matcher的构造方法是私有的,我们一般通过调用Pattern对象的matcher方法返回一个matcher。
String info = "名字:wulei 地址:hunan 电话:010-82350555";
Pattern p = Pattern.compile("(名字:\\w+\\s+)|(地址:\\w+\\s+)|(电话:\\d{3}-\\d{8})");
Matcher matcher = p.matcher(info);
4.2 Matcher类型的匹配方法
Matcher对象提供了三个不同的匹配方式:matches、 lookingAt()、find()。三个方法均返回boolean类型,当匹配到时返回true,没匹配到则返回false
boolean matches()
String info = "123abc"; Pattern p = Pattern.compile("\\d+"); Pattern p1 = Pattern.compile("\\d+\\w+"); Matcher matcher = p.matcher(info); Matcher matcher1 = p1.matcher(info); System.out.println(matcher.matches());//false System.out.println(matcher1.matches());//true
整个字符串必须符合正则表达式,才会返回true,否则返回false
boolean lookingAt()
字符串的开头符合使用的正则表达式,返回true。否则返回falseSystem.out.println(matcher.lookingAt()); //true、
String info = "123abc456def789"; Pattern p = Pattern.compile("\\d+"); Matcher matcher = p.matcher(info); while(matcher.find()){ System.out.println(matcher.group()); } 输出: 123 456 789
reset()
重置find()的指针。注意:lookingAt()会影响到find()查找的子字符串
String info = "123abc456def789"; Pattern p = Pattern.compile("\\d+"); Matcher matcher = p.matcher(info); System.out.println("执行lookingAt()后的group:"); matcher.lookingAt(); System.out.println(matcher.group()); //matcher.reset(); System.out.println("执行find():"); while(matcher.find()){ System.out.println(matcher.group()); } 输出: 执行lookingAt()后的group: 123 执行find(): 456 789
4.3 Matcher类型的详情方法
当我们执行完匹配操作后,我们常常需要获得匹配到的具体字符串。matcher对象能够使用group()、start()、end()方法来获取相关信息。
注意:这三个方法是基于我们matcher执行matches()|lookingAt()|find()并匹配成功的情况下才能使用,否则会抛出java.lang.IllegalStateException
返回匹配到的子字符串group()
返回匹配到的子字符串里的第index个分组,group(0)=group()。group(int index)
返回匹配到的子字符串在字符串中的索引位置start()
返回匹配到的子字符串里的第index个分组开始的索引。start(int index)
返回匹配到的子字符串的最后一个字符在字符串中的索引位置+1end()
end(int index)
现在我们使用一下稍微高级点的正则匹配操作,例如有一段文本,里面有很多数字,而且这些数字是分开的,我们现在要将文本中所有数字都取出来,利用java的正则操作是那么的简单
String info = "123abc456def789"; Pattern p = Pattern.compile("(\\d+)([a-z]+)"); Matcher matcher = p.matcher(info); while (matcher.find()){ System.out.println("start(1): " + matcher.start(1)); System.out.println("start(2): " + matcher.start(2)); System.out.println("end(1): " + matcher.end(1)); System.out.println("end(2): " + matcher.end(2)); } 输出: start(1): 0 start(2): 3 end(1): 3 end(2): 6 start(1): 6 start(2): 9 end(1): 9 end(2): 12
.
返回匹配到的子字符串里的第index个分组结束的索引+1。
Pattern p=Pattern.compile("\\d+"); Matcher m=p.matcher("我的QQ是:456456 我的电话是:0532214 我的邮箱是:aaa123@aaa.com"); while(m.find()) { System.out.println(m.group()); } 输出: 456456 0532214 123 如将以上while()循环替换成 while(m.find()) { System.out.println(m.group()); System.out.print("start:"+m.start()); System.out.println(" end:"+m.end()); } 则输出: 456456 start:6 end:12 0532214 start:19 end:26 123 start:36 end:39
int groupCount()
1.用于获取正则表达式中的小括号的个数。() 用于分组。
package com.se.day02.bPattern; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 研究一下groupCount(): */ public class PatternDemo07Matcher05 { public static void main(String[] args) { Pattern pattern = Pattern.compile("(((c)a)(t))s"); Matcher matcher = pattern.matcher("one cat, two cats in the yard"); /** * int groupCount(): * 作用:用于获取正则表达式中的小括号的个数。() 用于分组。 */ System.out.println(matcher.groupCount()); while (matcher.find()) { // 打印符合正则表达式的子串, 因此循环次数是xxxx次。 System.out.println(matcher.group()); } /** * 使用小括号的个数来循环, 可以使用group的重载方法: * String group(int group) * * 注意:想要使用()的个数进行遍历,需要将指针移动到字符串之前,然后还需要调用一下find方法 * * group(0): 表示的是对组进行拆分括号的整体的样子 * group(1): 表示第一个括号 * group(2): 表示第二个括号 */ matcher.reset(); matcher.find(); for (int i = 0; i <=matcher.groupCount(); i++) { System.out.println(matcher.group(i)); } } }
五 练习题以及八股文
邮箱验证
编写一个方法,使用正则表达式验证邮箱地址格式是否正确。要求:用户名可以包含字母、数字、点、下划线和连字符,域名包含至少一个点,且顶级域名至少2个字符。
手机号码验证
编写一个方法验证中国大陆手机号码格式(11位数字,以1开头,第二位为3-9)。使用正则表达式实现。
密码强度检查
创建一个方法检查密码强度,要求:
至少8位字符
包含至少一个大写字母
包含至少一个小写字母
包含至少一个数字
包含至少一个特殊字符(!@#$%^&*)
提取URL信息
编写程序从文本中提取所有的URL链接,并分别提取协议、域名和路径部分。使用正则表达式的分组捕获功能。
HTML标签处理
编写一个方法,使用正则表达式移除字符串中的所有HTML标签,但保留标签内的文本内容。
日期格式验证与提取
编写程序验证并提取文本中的日期(支持yyyy-MM-dd、yyyy/MM/dd、dd-MM-yyyy等格式),并将它们转换为统一的yyyy-MM-dd格式。
单词边界匹配
编写一个方法,使用正则表达式查找文本中完整单词"java"(不匹配"javascript"中的"java"),并统计出现次数。
IP地址验证
编写一个方法验证IPv4地址格式是否正确(0-255之间的数字,用点分隔)。要求使用正则表达式的前瞻断言功能。
字符串格式化处理
编写程序处理文本,将连续的空白字符(空格、制表符、换行符)替换为单个空格,并去除行首行尾空白。
复杂数据解析
给定一个包含姓名、年龄、邮箱的文本文件,每行格式如:"张三,25,zhangsan@example.com",使用正则表达式解析并验证每行数据的正确性,将有效数据存储到对象列表中。