文章目录
前言
正则表达式定义了字符串的模式。
正则表达式可以用来搜索、编辑或处理文本。
正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
Java 提供了 java.util.regex 包,通过 java.util.regex 包中的类和方法,我们可以在 Java 程序中使用正则表达式进行字符串处理。
一、java.util.regex 包
java.util.regex 包是 Java 标准库中用于支持正则表达式操作的包。
java.util.regex 包主要包括以下三个类:
- Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。 - Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。 - PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
二、语法
根据 Java Language Specification 的要求,Java 源代码的字符串中的反斜线被解释为 Unicode 转义或其他字符转义。因此必须在字符串字面值中使用两个反斜线 // ,表示正则表达式受到保护,不被 Java 字节码编译器解释。
正则表达式是由字符和特殊字符组成的模式,用于匹配和处理文本。以下是一些常用的正则表达式特殊字符:
- .:匹配任意单个字符。
- *:匹配前面的字符零次或多次。
- +:匹配前面的字符一次或多次。
- ?:匹配前面的字符零次或一次。
- \d:匹配数字字符。
- \w:匹配单词字符(字母、数字、下划线)。
- \s:匹配空白字符(空格、制表符等)。
除了特殊字符外,我们还可以使用一些限定符来指定匹配的次数:
- {n}:匹配前面的字符恰好 n 次。
- {n,}:匹配前面的字符至少 n 次。
- {n,m}:匹配前面的字符至少 n 次,最多 m 次。
实例:
public class RegexDemo1 {
public static void main(String[] args) {
// 校验qq号码,必须全部数字 6 - 20位
System.out.println("----不用正则表达式----");
System.out.println("251425998:" + checkQQ("251425998")); // 251425998:true
System.out.println("2514259a98:" + checkQQ("2514259a98")); // 2514259a98:false
System.out.println("null:" + checkQQ(null)); // null:false
System.out.println("2344:" + checkQQ("2344")); // 2344:false
System.out.println("----用正则表达式----");
System.out.println("251425998:" + checkQQ2("251425998")); // 251425998:true
System.out.println("2514259a98:" + checkQQ2("2514259a98")); // 2514259a98:false
System.out.println("null:" + checkQQ2(null)); // null:false
System.out.println("2344:" + checkQQ2("2344")); // 2344:false
}
/**
* 正则表达式,必须全部是数字,6 - 20位
* @param qq
* @return
*/
public static boolean checkQQ2(String qq) {
// \\d代表全数字,{6,20}代表6-20位
return qq != null && qq.matches("\\d{6,20}");
}
/**
* 正则表达式,必须全部是数字,6 - 20位
* @param qq
* @return
*/
public static boolean checkQQ(String qq) {
// 1、判断qq号码的长度是否满足要求
if (qq == null || qq.length() < 6 || qq.length() > 20) {
return false;
}
// 2、判断qq中是否全部是数字,不是返回false
for (int i = 0; i < qq.length(); i++) {
// 获取每位字符
char ch = qq.charAt(i);
// 判断这个字符是否不是数字,不是数字直接返回false
if (ch < '0' || ch > '9') {
return false;
}
}
return true; // 肯定合法了!
}
}
编译运行结果如下:
----不用正则表达式----
251425998:true
2514259a98:false
null:false
2344:false
----用正则表达式----
251425998:true
2514259a98:false
null:false
2344:false
三、步骤
在 Java 中使用正则表达式,通常需要经过以下几个步骤:
- 创建一个正则表达式的模式(Pattern)对象。
- 使用模式对象创建一个匹配器(Matcher)对象。
- 调用匹配器对象的方法进行匹配、查找或替换操作。
- 根据需要处理匹配结果。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @ClassName: RegexDemo2
* @Description: 使用正则表达式步骤
* @author: Zh
* @date: 2024/4/13 17:03
*/
public class RegexDemo2 {
public static void main(String[] args) {
String s1 = "Hello, World! This is a test string.";
String s2 = "test";
String s3 = ".*test.*";
// 1.创建一个正则表达式的模式(Pattern)对象
Pattern p = Pattern.compile(s2);
// 2.使用模式对象创建一个匹配器(Matcher)对象
Matcher m = p.matcher(s1);
// 3.调用匹配器对象的方法进行匹配、查找或替换操作
if (m.find()) {
// 4.根据需要处理匹配结果
System.out.println("找到匹配的字符串");
} else {
System.out.println("未找到匹配的字符串");
}
System.out.println("用test匹配:" + Pattern.matches(s2, s1)); // 用test匹配:false
// .匹配除"\r\n"之外的任何单个字符
// *零次或多次匹配前面的字符或子表达式
System.out.println("用.*test.*匹配:" + Pattern.matches(s3, s1)); // 用.*test.*匹配:true
}
}
编译运行结果如下:
找到匹配的字符串
用test匹配:false
用.*test.*匹配:true
四、Pattern类与Matcher类
1.matches( )
boolean flag = str.matches(regex);
快速判断能否在str中找到regex。
2.split( )
String[ ] ss = s.split(regex);
用regex把字符串分隔开来,返回String数组。
3.find( )
while(matcher.find(i)){
i++;
}
Matcher.find( )的功能是发现CharSequence里的,与pattern相匹配的多个字符序列。
4.group
A(B(C))D 里面有三个组:
group(0) 是 ABCD
group(1) 是 BC
group(2) 是 C
形式为 matcher.group( )
5.start( )和end( )
如果匹配成功,start( )会返回此次匹配的开始位置,end( )会返回此次匹配的结束位置,即最后一个字符的下标加一。
如果之前的匹配不成功(或者没匹配),那么无论是调用start( )还是end( ),都会引发一 个IllegalStateException。
matcher.start( );
matcher.end( );
6.replace替换
replaceFirst(String replacement)将字符串里,第一个与模式相匹配的子串替换成replacement。
replaceAll(String replacement),将输入字符串里所有与模式相匹配的子串全部替换成replacement。
String result = s.replaceAll(regex,ss);
String result = s.replaceFirst(regex,ss);
7.reset( )
用reset( )方法可以给现有的Matcher对象配上个新的CharSequence。
如果不给参数,reset( )会把Matcher设到当前字符串的开始处。
m.reset("java");
实例:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @ClassName: RegexDemo04
* @Description: 正则表达式Pattern类与Matcher类
* @author: Zh
* @date: 2024/4/13 15:23
*/
public class RegexDemo04 {
public static void main(String[] args) {
String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";
// 创建一个正则表达式的模式(Pattern)对象
Pattern pattern = Pattern.compile("\\w+");
// 使用模式对象创建一个匹配器(Matcher)对象
Matcher matcher = pattern.matcher(names);
// 1.boolean flag = str.matches(regex);
// 快速判断能否在str中找到regex。
System.out.println("1.matches:" + names.matches(".*小何.*"));
// 2.String[ ] ss = s.split(regex);
// 用regex把字符串分隔开来,返回String数组。
System.out.println("----2.split----");
String[] arrs = names.split("\\w+");
for (int i = 0; i < arrs.length; i++) {
System.out.println(arrs[i]);
}
// 3.replaceFirst(String replacement)
// 将字符串里,第一个与模式相匹配的子串替换成replacement。
String names1 = names.replaceFirst("\\w+", " ");
System.out.println("3.replaceFirst:" + names1);
// 4.replaceAll(String replacement)
// 将输入字符串里所有与模式相匹配的子串全部替换成replacement。
String names2 = names.replaceAll("\\w+", " ");
System.out.println("4.replaceAll:" + names2);
// 5.Matcher.find( )
// 发现CharSequence里的,与pattern相匹配的多个字符序列。
while (matcher.find()) {
// 6.如果匹配成功,start( )会返回此次匹配的开始位置。
// 7.如果匹配成功,end( )会返回此次匹配的结束位置,即最后一个字符的下标加一。
System.out.print("6.start index: " + matcher.start() + " ");
System.out.print("7.end index: " + matcher.end() + " ");
System.out.println(matcher.group());
}
}
}
编译运行结果如下:
1.matches:true
----2.split----
小路
蓉儿
小何
3.replaceFirst:小路 蓉儿43fdffdfbjdfaf小何
4.replaceAll:小路 蓉儿 小何
6.start index: 2 7.end index: 12 dhdfhdf342
6.start index: 14 7.end index: 28 43fdffdfbjdfaf
五、正则表达式的应用
1.校验:手机号码
String regex = "^1[3456789]\\d{9}$";
这个正则表达式用于匹配中国大陆地区的手机号码格式。我们可以逐步分解这个正则表达式以理解其含义:
- ^:表示字符串的开始。
- 1:匹配手机号码的第一位数字,即“1”。
- [3456789]:匹配手机号码的第二位数字,这里限定为“3”、“4”、“5”、“6”、“7”、“8”或“9”。
- \d{9}:匹配接下来的9位数字。\d 是一个转义序列,用于匹配任何数字(相当于 [0-9])。{9} 表示前面的模式(在这里是 \d,即一个数字)需要重复9次。
- $:表示字符串的结束。
2.校验:电子邮箱
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
该正则表达式用于匹配电子邮件地址的格式。我们可以逐步分解这个正则表达式以理解其含义:
- ^:表示字符串的开始。
- [A-Za-z0-9+_.-]+:这是一个字符类,匹配一个或多个(由 + 指定)在括号内列出的字符。这包括:
A-Z:任何大写字母。
a-z:任何小写字母。
0-9:任何数字。
+:加号字符。
_:下划线字符。
.:点字符。
-:连字符字符(注意,在这个字符类中,. 和 - 是特殊字符,所以它们本身也需要被匹配)。
这个部分匹配电子邮件地址的用户名部分,用户名可以包含字母、数字、加号、下划线、点或连字符。 - @:匹配电子邮件地址中的 @ 符号。
- [A-Za-z0-9.-]+:另一个字符类,与之前的类似,但这里仅包含字母、数字、点和连字符。这匹配电子邮件地址的域名部分。域名可以包含字母、数字、点或连字符。
- $:表示字符串的结束。
3.校验:身份证号
String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}([0-9]|X|x)$";
这个正则表达式用于匹配中国大陆地区的身份证号码格式。我们可以逐步分解这个正则表达式以理解其含义:
- ^:表示字符串的开始。
- [1-9]\d{5}:匹配身份证号码的前六位地区代码。其中 [1-9] 匹配第一位数字(地区代码的第一位不能为0),\d{5} 匹配接下来的五位数字。
- (18|19|20)\d{2}:匹配出生年份。(18|19|20) 匹配“18”、“19”或“20”,\d{2} 匹配接下来的两位数字,即年份的后两位。
- ((0[1-9])|(10|11|12)):匹配出生月份。(0[1-9]) 匹配“01”到“09”,(10|11|12) 匹配“10”、“11”或“12”,即匹配1到12月。
- (([0-2][1-9])|10|20|30|31):匹配出生日期。([0-2][1-9]) 匹配“01”到“29”,10|20|30|31 匹配“10”、“20”、“30”或“31”,即匹配1到31日。需要注意的是,这个正则并没有考虑到每个月具体的天数差异(比如2月可能只有28或29天),因此它只是一个大致的匹配。
- \d{3}:匹配顺序码,即身份证号码中的接下来三位数字。
- ([0-9]|X|x)$:匹配校验码。[0-9] 匹配任何一位数字,X|x 匹配大写或小写的“X”。
- $ 表示字符串的结束。
实例
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @ClassName: RegexTest3
* @Description: 正则表达式应用
* 手机号、邮箱、身份证号码
* @author: Zh
* @date: 2024/4/13 20:53
*/
public class RegexTest3 {
public static void main(String[] args) {
System.out.println("----校验:手机号码----");
String[] mobileNumbers = {
"13800138000",
"14725836900",
"12345678900", // 无效的手机号,位数不够
"123456789012", // 无效的手机号,位数太多
"abc1234567890" // 无效的手机号,包含非数字字符
};
for (String mobileNumber : mobileNumbers) {
if (isValidMobileNumber(mobileNumber)) {
System.out.println(mobileNumber + ":是有效的手机号。");
} else {
System.out.println(mobileNumber + ":是无效的手机号。");
}
}
System.out.println("----校验:电子邮箱----");
String[] emailAddresses = {
"test@example.com",
"example@gmail.com",
"invalid@", // 无效的邮箱,缺少域名部分
"@example.com", // 无效的邮箱,缺少用户名部分
"test.email@example", // 无效的邮箱,缺少顶级域名部分
"test..email@example.com", // 无效的邮箱,用户名中有多个点
"test@example..com", // 无效的邮箱,域名中有多个点
"test@example.com.", // 无效的邮箱,以点结尾
"test@.com" // 无效的邮箱,用户名或域名部分缺失
};
for (String email : emailAddresses) {
if (isValidEmail(email)) {
System.out.println(email + ":是有效的邮箱地址。");
} else {
System.out.println(email + ":是无效的邮箱地址。");
}
}
System.out.println("----校验:身份证号----");
String[] idCards = {
"11010519491231002X", // 有效的身份证号
"123456789012345678", // 无效的身份证号,位数不对
"11010519491231002A", // 无效的身份证号,最后一位不是数字或X
"11010519491231002", // 无效的身份证号,位数不够
"110105194912310021" // 无效的身份证号,位数太多
};
for (String idCard : idCards) {
if (isValidIDCardFormat(idCard)) {
System.out.println(idCard + ":是有效的身份证号格式。");
} else {
System.out.println(idCard + ":是无效的身份证号格式。");
}
}
}
/**
* 校验:手机号码
* @param mobileNumber
* @return
*/
public static boolean isValidMobileNumber(String mobileNumber) {
// 中国手机号的正则表达式
// 1开头,第二位可以是3456789,后面跟着9位数字
String regex = "^1[3456789]\\d{9}$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(mobileNumber);
return matcher.matches();
}
/**
* 校验:邮箱
* @param email
* @return
*/
public static boolean isValidEmail(String email) {
// 邮箱地址的正则表达式
// 这个正则表达式不是最严格的,但能够匹配大多数常见的邮箱地址格式
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
return matcher.matches();
}
/**
* 校验:身份证号码
* @param idCard
* @return
*/
public static boolean isValidIDCardFormat(String idCard) {
// 身份证号码的正则表达式,17位数字加上一位数字或X
String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}([0-9]|X|x)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(idCard);
return matcher.matches();
}
}
编译运行结果如下:
----校验:手机号码----
13800138000:是有效的手机号。
14725836900:是有效的手机号。
12345678900:是无效的手机号。
123456789012:是无效的手机号。
abc1234567890:是无效的手机号。
----校验:电子邮箱----
test@example.com:是有效的邮箱地址。
example@gmail.com:是有效的邮箱地址。
invalid@:是无效的邮箱地址。
@example.com:是无效的邮箱地址。
test.email@example:是有效的邮箱地址。
test..email@example.com:是有效的邮箱地址。
test@example..com:是有效的邮箱地址。
test@example.com.:是有效的邮箱地址。
test@.com:是有效的邮箱地址。
----校验:身份证号----
11010519491231002X:是有效的身份证号格式。
123456789012345678:是无效的身份证号格式。
11010519491231002A:是无效的身份证号格式。
11010519491231002:是无效的身份证号格式。
110105194912310021:是有效的身份证号格式。