Java_正则表达式
Pattern类(java.util.regex.Pattern)
Pattern是一个不可变类且线程安全。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。
// 直接调用 Pattern 类中的静态boolean类型的方法 matches 判断
// 如果一个模式多次被使用,编译一次并重用它将比每次调用此方法更有效
System.out.println(Pattern.matches("a*b", "aab")); // true
System.out.println(Pattern.compile("a*b").matcher("aab").matches()); // 表现方式同上
// 经典写法
Pattern p = Pattern.compile("a*b"); //通过静态方法创建 Pattern 对象
Matcher m = p.matcher("aab");
System.out.println(m.matches()); // true
System.out.println(p.pattern()); // a*b 返回编译此模式的正则表达式
System.out.println(p.flags()); // 0 返回此模式的匹配标志
String [] s = p.split("adbcacbfaob");
String [] s1 = p.split("adbcacbfaob",2);
Stream<String> s2 = p.splitAsStream("adbcacbfaob");
System.out.println(Arrays.toString(s)); // [ad, cac, fao] 将给定的输入序列分成这个模式的匹配
System.out.println(Arrays.toString(s1)); // [ad, cacbfaob]
System.out.println(s2.count()); // 返回该流中的元素个数
// 指定过滤模式
Pattern p1 = Pattern.compile("a\\d+?b", Pattern.CASE_INSENSITIVE); // 等同于(?i)a\\d+?b
System.out.println(p1.matcher("A12412B").matches()); // true 不区分大小写匹配
Matcher类(java.util.regex.Matcher)
Matcher也是一个不可变类. 通过调用Pattern的matcher方法创建匹配器。可以使匹配执行三种不同的匹配操作:
- matches 将整个输入序列与该模式匹配
- lookingAt 将输入序列从头开始于该模式匹配
- find 扫描输入序列以查找该模式匹配的下一个子序列
String t = "a1test2A34test4";
Pattern p = Pattern.compile("(?i)a\\d+?"); // 忽略大小写匹配以a开头且尽可能少的数字字符
Matcher m = p.matcher(t);
// 遍历匹配到的字符串
while(m.find()){
System.out.println("find: start:"+m.start() +" end:" +m.end() +" group:"+m.group());
//find: start:0 end:2 group:a1
//find: start:7 end:9 group:A3
}
System.out.println(m.find()); // false 遍历完后,再次查找返回false
// 通过查找匹配的字符的偏移量,来确定是否匹配
System.out.println(m.matches()); // false 匹配整个字符串
try { // 因为没有匹配到字符串,所以会抛出异常
System.out.println("matches: start:" + m.start() + " end:" + m.end());
}catch(Exception e){
System.out.println(e.getMessage()); //No match available (java.lang.IllegalStateException:)
}
System.out.println(m.lookingAt());// true 从头开始匹配
System.out.println("lookingAt: start:"+m.start()+" end:"+m.end()+" group:"+m.group());//lookingAt: start:0 end:2 group:a1
System.out.println(m.find()); // true 匹配下一个子序列,这里返回的是最后一个匹配
System.out.println("find: start:"+m.start() +" end:" +m.end() +" group:"+m.group()); // find: start:7 end:9 group:A3
System.out.println(m.find()); // false 已经全部查找完成
以上是三种匹配方式。有时候我们需要对字符串或文本进行替换,那Matcher类有没有提供相应的方法呢?也提供了几种替换的方法
- replaceFirst 将匹配第一个子序列替换为给定的字符串
- replaceAll 将匹配每个子序列替换为给定的字符串
- appendReplacement和appendTail 实现非终端和终端的添加和替换步骤
// 替换字符串
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString()); // one dog two dogs in the yard
System.out.println(m.replaceAll("pig")); // one pig two pigs in the yard
System.out.println(m.replaceFirst("monkey")); // one monkey two cats in the yard
Matcher类中还有其他,如重置匹配器,指定匹配范围等。这里示范重置匹配器、组别相关的方法
String t = "a1test2A34test4";
Pattern p = Pattern.compile("(?i)(a\\d+)([a-z]+)(\\d)(a\\d+?)(\\d)([a-z]+)(\\d)");
Matcher m = p.matcher(t);
Matcher newM = m.reset("a1test2A36LTest4");
System.out.println(newM.groupCount()); // 7 组(不包括group(0))
if(m.find()){
System.out.println(newM.group(1)); // a1
System.out.println(newM.group(2)); // test
System.out.println(newM.group(3)); // 2
System.out.println(newM.group(4)); // A3
System.out.println(newM.group(5)); // 6
System.out.println(newM.group(6)); // LTest
System.out.println(newM.group(7)); // 4
System.out.println(newM.group(0)); // 匹配 a1test2A36LTest4
/*
for(int i=0;i<newM.groupCount();i++) {
System.out.println(newM.group(i));
}*/
}else{
System.out.println("---");
}
正则表达式语法
正则表达式,又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。它并不仅限于某一种语言,但是在每种语言中有细微的差别。
字符 | 说明 |
---|---|
\ | 将下一字符标记为特殊字符、文本、反向引用或八进制转义符 |
^ | 匹配字符串开始的位置 |
$ | 匹配字符串结尾的位置 |
. | 匹配任意单个字符("\r\n"除外) |
* | 重复零次或多次匹配前面的字符或子表达式, 等效 |
+ | 一次或多次,等效 |
? | 零次或一次,等效 |
重复n次 | |
至少匹配n次或匹配多次 | |
至少匹配n次或至多匹配多次 | |
x|y | 匹配x 或y |
[a-z] | 匹配指定范围内的任何字符. 指定字符[abc],不匹配包含的字符[^abc] |
[0-9] | 匹配指定范围内的任何数字. 指定字数[123],不匹配包含的数字[^123] |
\b | 匹配一个字边界,字与空格间的位置 |
\B | 非字边界匹配 |
\d | 数字字符匹配. 等效于 [0-9] |
\D | 非数字字符匹配. 等效于 [^0-9] |
\w | 匹配任何字类字符,包括下划线. 等效[A-Za-z0-9_] |
\W | 与任何非单词字符匹配. 等效[^A-Za-z0-9_] |
\s | 匹配任何空白字符,包括空格、制表符、换页符等. 等效 [ \f\n\r\t\v] |
\S | 匹配任何非空白字符. 等效[^ \f\n\r\t\v] |
(pattern) | 匹配pattern并捕获该匹配的子表达 |
(?:pattern) | 匹配pattern但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配 |
(?=pattern) | 执行正向预测先行搜索的子表达式,该表达式匹配处于匹pattern 的字符串的起始点的字符串.它是一个非捕获匹配,即不能捕获供以后使用的匹配 |
(?!pattern) | 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹pattern 的字符串的起始点的搜索字符串.它是一个非捕获匹配,即不能捕获供以后使用的匹配 |
(?i) | 表示忽略大小写(仅匹配US-ASCII字符集中的字符), 等效 Pattern.CASE_INSENSITIVE |
(?x) | 表示允许空格和注释格式,将忽略空格,并且以#开头的嵌入式注释将被忽略,直到行尾, 等效Pattern.COMMENTS |
(?m) | 表示启用多行模式, 表达式^和$分别匹配行终止符或输入序列的结尾, 等效Pattern.MULTILINE |
(?s) | 表示启用单行模式, 表达式.匹配任何字符,包括行终止符。 默认情况下,此表达式与行终止符不匹配, 等效Pattern.DOTALL |
(?u) | 启用 Unicode 感知的大小写折叠, 不区分大小写的匹配(由CASE_INSENSITIVE标志启用)以与Unicode标准一致的方式完成. 默认情况下,不区分大小写的匹配假定仅匹配US-ASCII字符集中的字符, 等效Pattern.UNICODE_CASE |
注:使用正则的时候需要注意,在java中的反斜杠( \ )需要进行转义.
正则表达式实例
- IP地址匹配:
^(?:(?:1[0-9][0-9]\.)|(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$
((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))
- 身份证匹配:
(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$
- 网址URL匹配:
[a-zA-z]+://[^\s]*
^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
- 邮箱地址匹配:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
^[a-z]([a-z0-9]*[-_]?[a-z0-9]+)*@([a-z0-9]*[-_]?[a-z0-9]+)+[\.][a-z]{2,3}([\.][a-z]{2})?$
注:
正则相关教程:https://www.oschina.net/question/12_9507
正则相关实例:https://c.runoob.com/front-end/854
正则匹配工具下载
正则在线工具
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律