Java正则表达式1
一.正则表达式简介
正则表达式,本质上就是字符串,是一种规则,用来匹配,搜索,编辑,操作文本的,java中提供了java.util.regex
包来与正则表达式进行模式匹配。
下面以一个简单的例子看看正则表达式,会有个更直观的印象:
public class RegexDemo1 {
public static void main(String[] args) {
Pattern p = Pattern.compile("[0-9]{2,3}");
Matcher m = p.matcher("123");
System.out.println(m.matches());// 输出: true
}
}
上述例子中[0-9]{2,3}
就是所谓的正则表达式,{2,3}是匹配由至少2个数字,至多3个数字的字符串,前面[0-9]是指数字0-数字9,也就是十个数字。
java中提供了java.util.regex
包,包里提供了两个类:Pattern和Matcher
Pattern就是一种模式,利用它的静态方法compile,编译正则表达式,得到一种匹配的模式,再利用matcher方法进行字符串的匹配,得到匹配结果Matcher,最后由Matcher处理结果。
二.Pattern类和Matcher类
- Pattern类中提供了以下几个常用的方法:
static Pattern compile(String regex)
:将给定的正则表达式编译到模式中。Matcher matcher(CharSequence input)
:创建匹配器,返回Matcher类实例。String[] split(CharSequence input)
:将匹配到的数据拆分。
- Matcher类中提供了以下几个常用的方法:
boolean matches()
:执行匹配验证,当整个匹配时才返回true。String replaceAll(String replacement)
:替换字符串。String group(int group)
:返回指定组的匹配数据。
三.字符串String类对正则的支持
字符串String类对正则表达式有四个内置的可以运行正则表达式的方法,分别是:matches(),split() ,replaceAll(),replaceFirst()
注意:replace()函数是不支持正则表达式的!
boolean matchers(String regex)
:当且仅当整个字符串匹配时返回true。String[] split(String regex)
:根据给定的正则表达式的匹配来拆分字符串。String replaceAll(String regex, String replacement)
:使用给定的replacement替换字符串所有匹配给定正则表达式的子字符串。String replaceFirst(String regex, String replacement)
:使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串。
public class RegexDemo2 {
public static void main(String[] args) {
String s = "hello java abc";
boolean s1 = s.matches("hello java");
System.out.println(s1);
System.out.println("------------------------");
String[] s2 = s.split("\\s");
for (String s0 : s2) {
System.out.println(s0);
}
System.out.println("-------------------------");
String s3 = s.replaceAll("\\s", "+");
System.out.println(s3);
System.out.println("-------------------------");
String s4 = s.replaceFirst("\\s", "-");
System.out.println(s4);
System.out.println("-------------------------");
}
}
输出结果:
false
------------------------
hello
java
abc
-------------------------
hello+java+abc
-------------------------
hello-java abc
-------------------------
四.正则表达式的规则
-
常见的匹配符号
-
.
匹配所有的单个字符,除了换行符。
-
^regex
匹配以字符串开头
-
regex$
匹配以字符串结尾
-
[abc]
复选集定义,匹配字符a,或b,或c
-
[^abc]
在中括号中插入^符号,表示否定模式
匹配所有的字符,除了a,b,c三个
-
[a-z1-9]
表示范围的匹配,匹配字母a到z和数字1到9,比如可以匹配到a4
-
a|b
或的选择,可以匹配a或者b,只会二选一
-
-
元字符
-
\d
匹配一个数字,相当于是
[0-9]
的简写,当要匹配一个数字时,可以直接写\d,简化了写[0-9] -
\D
匹配一个非数字,相当于是
[^0-9]
的简写 -
\s
匹配一个空格,包括tab键(\t)
-
\S
匹配一个非空格
-
\w
匹配一个单词字符(包括大小写字母,数字,下划线),相当于是
[a-zA-Z0-9_]
的简写 -
\W
匹配一个非单词字符(就是除了大小写字母,数字和下划线之外的字符)
-
-
限定符
-
*
:匹配大于等于0个任意字符,可以是0个,也可以是无数个。
比如:X*表示匹配0个或者任意多个字符X,.*则表示匹配任何字符串
-
+
:匹配大于等于1个任意字符,至少是1个,可以是无数个。
-
?
:匹配0个或1个任意字符,至少是0个,至多是1个。
-
{n}
:表示只匹配n个任意字符。
-
{n,m}
:表示只匹配n-m个任意字符,最少n个,最多m个。
-
*?
:如果?是限定符*,+,?或者{}后面的第一个字符,那么表示这是一种非贪婪模式
非贪婪模式:就是指尽可能的少匹配,默认的是贪婪模式。
比如
c(.*)b
,默认是贪婪模式,是尽可能多匹配,而.*是匹配任意字个符,那么在匹配caabaabaab时,因为贪婪模式,中间的字符都属于匹配范围,只要最后一个b,最后匹配结果是:caabaabaab而
c(.*?)b
,则是非贪婪匹配,是尽可能少的匹配,所以对于.*,应该是尽快能少的取,所以对于caabaabaab会被匹配,但是匹配得到是caab,中间尽量少匹配字符,所以在遇到第一个b时候结束匹配了。public class RegexDemo3 { public static void main(String[] args) { Pattern p = Pattern.compile("c.*b"); Matcher m = p.matcher("caabaabaab"); if (m.find()) { System.out.println("caabaabaab matches: " + m.group(0)); } // 输出:caabaabaab matches: caabaabaab Pattern p1 = Pattern.compile("c.*?b"); Matcher m1= p1.matcher("caabaabaab"); if (m1.find()) { System.out.println("caabaabaab matches: " + m1.group(0)); }// 输出:caabaabaab matches: caab } }
-
-
分组
使用小括号(),可以起到对正则表达式进行分组的作用,这样子我们可以使用Matcher类的group()函数来获取。
分组之后的引用也分为几种:
-
分组和反向引用
使用分组后会在正则表达式中创建反向引用,反向引用会保存匹配到的字符串片段,后续可以直接通过$来引用,$0表示匹配到的完整模式的字符串,$1表示第一个分组的反向引用,$2表示第二个分组的方向引用,依次类推.......
public class RegexDemo4 { public static void main(String[] args) { // 去除空格,得到Hello,java! String str = "Hello , java !"; String p = "(\\w)(\\s+)([,!])"; System.out.println(str.replaceAll(p, "$1$3")); // 输出:Hello, java! } }
解析:String p = "(\w)(\s+)([,!])";
这一个正则表达式分了三个组:
$0 会匹配
(\w)(\s+)([,!])
的结果,也就是o空格,
和a空格!
$1 会匹配
(\w)
的结果,也就是o
和a
$2 会匹配
(\s+)
的结果,也就是空格
和空格
$3 会匹配
[,!]
的结果,也就是,
和!
所以在调用replaceAll时,所有匹配到的结果,也就是
o空格,
会被替换为$1$3匹配到的结果o,
,而a空格!
也会被替换为$1$3匹配的结果a!
-
分组但不反向引用---(?😃
如果我们在小括号内开头加入
?:
,那么这个模式就只是分组,不会创建方向引用。将上面代码做下小修改,如下:
public class RegexDemo4 { public static void main(String[] args) { // 去除空格,得到Hello,java! String str = "Hello , java !"; String p = "(?:\\w)(\\s+)([,!])"; System.out.println(str.replaceAll(p, "$1$3")); } }
这样子将会报一个错误:
Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 3
因为第一个分组(\w)被改为了(?:\w),只是分组,不会创建反向引用,所以这时候就没有3个反向引用了,只有两个,所以找不到group 3
-
分组的反向引用的副本
在使用反向引用时候,也可以不用$去引用,而是使用一个别名,也就是反向引用的副本,只要在小括号中加入?<name>,就会把反向引用保存为一个名字为name的副本了,后续使用时候直接使用name就可以得到反向引用。
public class RegexDemo4 { public static void main(String[] args) { // 去除空格,得到Hello,java! String str = "Hello,java"; Pattern p = Pattern.compile("(?<First>\\w*),(?<Second>\\w*)"); Matcher m = p.matcher(str); while (m.find()) { System.out.println(m.group(1));// 输出:Hello System.out.println(m.group("First"));// 输出:Hello System.out.println(m.group(2));// 输出:java System.out.println(m.group("Second"));// 输出:java } } }
-
-
指定正则表达式的模式
可以在正则表达式语句的开头指定模式,有以下几种模式可以指定:
- (?i):正则表达式忽略大小写。
- (?s):表示单行模式(s表示single),那么正则表达式的.就会匹配所有字符,包括换行符了。
- (?m):表示多行模式(m表示Multi-line),可以使用^和$匹配每一行的开始和结束。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理