Java 正则表达式(Regex,Regular Expression)是用来描述字符串模式的工具,它允许你检查一个字符串是否符合某种模式,或者通过某些规则对字符串进行匹配、替换、分割等操作。Java 中的正则表达式由 java.util.regex 包提供,包括 Pattern 和 Matcher 类。
1. 正则表达式基础
正则表达式由字符、元字符(Metacharacters)以及特殊的规则组合而成。常用的正则表达式元字符包括:
.:匹配任意单个字符(除换行符之外)。^:匹配输入字符串的开始。$:匹配输入字符串的结束。*:匹配前面的子表达式零次或多次。+:匹配前面的子表达式一次或多次。?:匹配前面的子表达式零次或一次。{n}:匹配前面的子表达式恰好 n 次。{n,}:匹配前面的子表达式至少 n 次。{n,m}:匹配前面的子表达式至少 n 次,至多 m 次。[]:匹配括号内的任意字符。|:表示逻辑“或”。():分组,用于将多个字符或表达式作为一个单元处理。\d:匹配一个数字字符,相当于[0-9]。\D:匹配一个非数字字符,相当于[^0-9]。\w:匹配一个字母、数字或下划线字符,相当于[a-zA-Z0-9_]。\W:匹配一个非字母、非数字或非下划线字符,相当于[^a-zA-Z0-9_]。\s:匹配任何空白字符(空格、制表符、换行符等)。\S:匹配任何非空白字符。
2. Pattern 类
Pattern 类是 Java 正则表达式的核心,它是正则表达式的抽象表示。正则表达式字符串会被编译成一个 Pattern 对象,并且可以被多个 Matcher 对象重用。
2.1 创建 Pattern 对象
import java.util.regex.*;
Pattern pattern = Pattern.compile("a*b"); // 编译正则表达式
2.2 Pattern 类的常用方法
compile(String regex):编译正则表达式并返回Pattern对象。matcher(CharSequence input):返回一个Matcher对象,用于对输入字符串进行匹配。split(CharSequence input):将字符串按正则表达式分割。matches():判断字符串是否完全符合正则表达式。
3. Matcher 类
Matcher 类提供了对字符串进行正则匹配的功能。通过 Pattern 类生成 Matcher 对象后,可以调用 Matcher 类提供的方法来执行匹配、查找、替换等操作。
3.1 创建 Matcher 对象
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaab");
3.2 Matcher 类的常用方法
find():查找是否存在匹配项。如果存在,返回true,否则返回false。matches():尝试匹配整个字符串,如果字符串完全符合正则表达式,则返回true,否则返回false。group():返回当前匹配项的子字符串。start():返回匹配项在原字符串中的开始位置。end():返回匹配项在原字符串中的结束位置。replaceAll(String replacement):用指定的字符串替换所有匹配的子串。
4. 正则表达式示例
4.1 字符串匹配
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
// 编译正则表达式
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaab");
// 查找匹配项
if (matcher.matches()) {
System.out.println("字符串完全匹配");
} else {
System.out.println("字符串不匹配");
}
}
}
输出:
字符串完全匹配
4.2 查找匹配项
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\d+"); // 匹配一个或多个数字
Matcher matcher = pattern.matcher("abc123xyz456");
// 查找匹配项
while (matcher.find()) {
System.out.println("找到匹配项: " + matcher.group());
}
}
}
输出:
找到匹配项: 123
找到匹配项: 456
4.3 使用分组
正则表达式中的分组(())可以提取字符串的一部分。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(\\d+)-(\\d+)");
Matcher matcher = pattern.matcher("123-456");
if (matcher.find()) {
System.out.println("第一个分组: " + matcher.group(1)); // 输出 123
System.out.println("第二个分组: " + matcher.group(2)); // 输出 456
}
}
}
输出:
第一个分组: 123
第二个分组: 456
4.4 替换匹配项
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\d+"); // 匹配数字
Matcher matcher = pattern.matcher("abc123xyz456");
// 用 "#" 替换所有的数字
String result = matcher.replaceAll("#");
System.out.println(result); // 输出 abc#xyz#
}
}
输出:
abc#xyz#
4.5 分割字符串
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String str = "apple,banana,orange";
String[] fruits = str.split(",");
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
输出:
apple
banana
orange
5. 正则表达式的常用应用
5.1 验证邮箱
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String email = "test@example.com";
String regex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
if (matcher.matches()) {
System.out.println("邮箱格式正确");
} else {
System.out.println("邮箱格式不正确");
}
}
}
输出:
邮箱格式正确
5.2 验证手机号(以中国为例)
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String phone = "13812345678";
String regex = "^(1[3-9])\\d{9}$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(phone);
if (matcher.matches()) {
System.out.println("手机号格式正确");
} else {
System.out.println("手机号格式不正确");
}
}
}
输出:
手机号格式正确
5.3 验证密码(要求至少8个字符,包括大小写字母和数字)
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String password = "Password123";
String regex = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).{8,}$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(password);
if (matcher.matches()) {
System.out.println("密码格式正确");
} else {
System.out.println("密码格式不正确");
}
}
}
输出:
密码格式正确
6. 正则表达式的性能优化
在 Java 中使用正则表达式时,通常会涉及性能方面的问题,尤其是当正则表达式较为复杂时。以下是一些性能优化的建议:
6.1 使用预编译的正则表达式
如果你在多个地方使用相同的正则表达式,推荐使用 Pattern.compile() 方法将其预编译为 Pattern 对象,这样可以避免每次使用时重复编译正则表达式,从而提高性能。
Pattern pattern = Pattern.compile("\\d+"); // 预编译正则表达式
Matcher matcher = pattern.matcher("1234");
6.2 使用非贪婪模式
默认情况下,正则表达式是贪婪的,即尽可能匹配更多的字符。有时使用非贪婪模式(即“懒惰模式”)可以提高效率,尤其是在处理大量数据时。非贪婪模式使用 *?、+?、?? 等。
例如,".*" 是贪婪模式,会尽可能多地匹配字符,而 ".*?" 是非贪婪模式,会尽量少匹配字符。
Pattern pattern = Pattern.compile("<.*?>"); // 非贪婪模式
6.3 避免复杂的正则表达式
一些复杂的正则表达式可能会导致性能问题。尽量避免过多的分组、回溯和使用不必要的高级功能。尽量简化正则表达式,并在需要时逐步优化。
6.4 使用正则表达式时避免过多使用 find() 方法
在多次执行 find() 方法时,如果模式是 find() 调用的条件,每次调用都会使得正则表达式引擎进行多次计算。因此,当你知道需要多次查找时,可以考虑使用一次 find() 来匹配所有结果,减少多次匹配过程。
7. 正则表达式的常见应用场景
正则表达式在实际开发中有广泛的应用,以下是一些常见的应用场景:
7.1 字符串验证
正则表达式常常用于对用户输入进行验证。例如,验证邮箱、手机号、身份证号等格式是否正确。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String email = "user@example.com";
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
if (matcher.matches()) {
System.out.println("有效邮箱");
} else {
System.out.println("无效邮箱");
}
}
}
7.2 文本搜索与替换
正则表达式可以用来查找和替换字符串中的某些内容。例如,删除文本中的 HTML 标签或替换敏感词。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String text = "This is a <b>test</b> message.";
String regex = "<[^>]*>"; // 匹配 HTML 标签
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
// 替换 HTML 标签
String result = matcher.replaceAll("");
System.out.println(result); // 输出 "This is a test message."
}
}
7.3 从文本中提取信息
正则表达式非常适合用来从文本中提取出特定的信息。例如,从日志文件中提取 IP 地址、日期或其他关键信息。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String log = "192.168.1.1 - - [12/Mar/2025:15:20:01 +0000] \"GET /index.html\"";
String regex = "(\\d+\\.\\d+\\.\\d+\\.\\d+)"; // 提取 IP 地址
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(log);
if (matcher.find()) {
System.out.println("IP 地址: " + matcher.group(1));
}
}
}
输出:
IP 地址: 192.168.1.1
7.4 分析与处理文件格式
在处理 CSV、日志文件、XML、JSON 等文件格式时,正则表达式是一个非常强大的工具。例如,处理 CSV 文件中的字段分隔、XML 标签的提取等。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String csv = "name,age,city\nAlice,30,New York\nBob,25,Boston";
String regex = "(\\w+),(\\d+),(\\w+)"; // CSV 文件中的每一行
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(csv);
while (matcher.find()) {
System.out.println("Name: " + matcher.group(1) + ", Age: " + matcher.group(2) + ", City: " + matcher.group(3));
}
}
}
输出:
Name: Alice, Age: 30, City: New York
Name: Bob, Age: 25, City: Boston
8. 总结
- 正则表达式的基本概念:通过使用元字符和特殊语法,正则表达式允许你描述和匹配复杂的字符串模式。
- 常见方法:通过
Pattern和Matcher类,你可以在 Java 中使用正则表达式进行字符串匹配、替换、分割和提取操作。 - 应用场景:正则表达式在验证输入、文本处理、日志分析、文件解析等方面具有广泛应用。
- 优化:合理使用预编译、非贪婪模式以及避免过于复杂的正则表达式,有助于提高性能。
如果有其他更复杂的正则表达式问题或具体的应用场景,欢迎继续提问!