2360 字
12 分钟
正则表达式
2025-11-03
无标签

正则表达式(Regular Expression)是一种强大的文本处理工具,它通过定义特定模式来匹配、查找和替换文本。Java 自 JDK 1.4 起内置了对正则表达式的支持,主要通过 java.util.regex 包中的 Pattern、Matcher 和 PatternSyntaxException 类实现。

一、正则表达式基础#

1.核心类与工作流程#

两个核心类:

  • Pattern类:编译正则表达式后创建的模式对象,线程安全,可复用
  • Matcher类: 对输入字符串进行匹配操作的引擎,线程不安全
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
// 1. 编译正则表达式,生成Pattern对象
Pattern pattern = Pattern.compile("a*b");
// 2. 创建Matcher对象,关联待匹配的字符串
Matcher matcher = pattern.matcher("aaaaab");
// 3. 执行匹配操作
boolean matchFound = matcher.matches();
System.out.println(matchFound); // 输出: true
}
}
Pattern pattern = Pattern.compile("\\d+"); // 编译正则表达式,匹配一个或多个数字
Matcher matcher = pattern.matcher("123abc456");
while (matcher.find()) {
System.out.println(matcher.group()); // 输出匹配到的数字:123、456
}

常用函数:

  • matcher.find():查找字符串中是否有匹配正则的子串(可多次调用,每次找下一个匹配)。
  • matcher.group():获取当前匹配到的子串(支持分组提取,如 group(1) 取第一个分组)。
  • matcher.matches():判断整个字符串是否完全匹配正则(与 Pattern.matches 功能一致)。
  • matcher.replaceAll(String replacement):替换所有匹配的子串。
import java.util.regex.*;
public class RegexDemo {
public static void main(String[] args) {
String input = "价格:99元,数量:3个,总价:297元";
String regex = "\\d+"; // 正则规则:匹配1个或多个数字
// 步骤1:用Pattern编译正则规则
Pattern pattern = Pattern.compile(regex);
// 步骤2:用Pattern创建Matcher,绑定要匹配的字符串
Matcher matcher = pattern.matcher(input);
// 步骤3:用Matcher查找并提取所有匹配的数字
System.out.println("提取到的数字:");
while (matcher.find()) { // 循环查找下一个匹配的子串
String number = matcher.group(); // 获取当前匹配的子串
System.out.println(number);
}
}
}
提取到的数字:
99
3
297

2.正则表达式语法基础#

Java 正则表达式支持的基本元字符和语法包括:

(1)字符类

  • [abc]:匹配 a、b 或 c 中的任意一个字符
  • [^abc]:匹配除 a、b、c 之外的任意字符
  • [a-zA-Z]:匹配任意大小写字母
  • [0-9]:匹配任意数字

(2)预定义字符类

  • .:匹配任意单个字符(除换行符)
  • \d:等价于 [0-9],匹配数字
  • \D:等价于 [^0-9],匹配非数字
  • \s:匹配空白字符(空格、制表符、换行符等)
  • \S:匹配非空白字符
  • \w:等价于 [a-zA-Z0-9_],匹配字母、数字和下划线
  • \W:等价于 [^a-zA-Z0-9_],匹配非字母、数字和下划线

(3)数量词

  • X?:X 出现 0 次或 1 次(可选)
  • X*:X 出现 0 次或多次
  • X+:X 出现 1 次或多次
  • X{n}:X 恰好出现 n 次
  • X{n,}:X 至少出现 n 次
  • X{n,m}:X 出现次数介于 n 和 m 之间(含)

(4)边界匹配

  • ^:匹配输入的开始位置
  • $:匹配输入的结束位置
  • \b:匹配单词边界(如空格、标点或字符串首尾)

一、普通字符(Literal Characters)

定义:没有特殊含义的字符,直接匹配自身。

示例:

正则 abc 匹配字符串中连续的 abc(如 xyzabc123 中的 abc)

二、特殊字符(Metacharacters)

以下字符在正则中有特殊含义,需用反斜杠 \ 转义(如匹配 * 需写为 \*):

^ $ . * + ? ( ) [ ] { } | \

三、常用匹配规则

  1. 匹配任意字符:.

匹配除换行符(\n)外的任意单个字符。

示例:

正则 a.b 匹配 aab、acb、a1b(中间是任意字符),不匹配 ab(长度不够)、a\nb(含换行)

  1. 边界匹配:^ 和 $
  • ^:匹配字符串的开头(如 ^abc 匹配以 abc 开头的字符串,如 abc123)。
  • :匹配字符串的结尾(如xyz:匹配字符串的结尾(如 xyz 匹配以 xyz 结尾的字符串,如 123xyz)。

示例:

正则 ^abc$ 仅匹配完整字符串 abc(精确匹配,常用于格式验证)。

  1. 重复匹配:*、+、?
  • *:匹配前面的元素0 次或多次(尽可能多,贪婪模式)。

示例:a* 匹配 ""(空)、a、aa、aaa 等。

  • +:匹配前面的元素1 次或多次。

示例:a+ 匹配 a、aa、aaa 等(至少 1 个 a)。

  • ?:匹配前面的元素0 次或 1 次。

示例:a? 匹配 "" 或 a(最多 1 个 a)。

  1. 限定重复次数:{n}、{n,}、{n,m}
  • {n}:匹配前面的元素恰好 n 次。

示例:a{3} 匹配 aaa(刚好 3 个 a)。

  • {n,}:匹配前面的元素至少 n 次。

示例:a{2,} 匹配 aa、aaa、aaaa 等(至少 2 个 a)。

  • {n,m}:匹配前面的元素至少 n 次,最多 m 次。

示例:a{1,3} 匹配 a、aa、aaa(1-3 个 a)。

  1. 字符集:[ ]

匹配括号内的任意一个字符(仅 1 个)。 规则:

  • 范围用 - 表示(如 [0-9] 匹配任意数字,[a-z] 匹配任意小写字母)。
  • 否定用 ^ 表示(如 [^0-9] 匹配非数字字符)。
  • 特殊字符在 [] 内无需转义(如 [.+] 直接匹配 .、、+)。

示例: [a-zA-Z0-9] 匹配任意字母或数字(类似 \w,见下文)。

  1. 预定义字符集(快捷写法)
语法含义等价写法
\d匹配任意数字(0-9)[0-9]
\D匹配任意非数字[^0-9]
\w匹配字母、数字、下划线[a-zA-Z0-9_]
\W匹配非字母、数字、下划线[^a-zA-Z0-9_]
\s匹配空白字符(空格、制表符 \t、换行 \n 等)[ \t\n\r\f]
\S匹配非空白字符[^ \t\n\r\f]
  1. 逻辑或:| 匹配 | 前后的任意一个模式。 示例: 正则 abc|def 匹配 abc 或 def(如 xyzabc 中的 abc,def123 中的 def)。

  2. 分组:( ) 将多个字符视为一个整体,可结合重复符号使用。 示例: (ab)+ 匹配 ab、abab、ababab 等(ab 重复 1 次及以上)。

四、示例:常用正则场景

  • 验证手机号(中国大陆):^1\d{10}$,^1 开头是 1,\d{10} 后跟 10 位数字,$ 结尾,共 11 位)。
  • 提取所有邮箱:\w+@\w+\.\w+,\w+ 匹配用户名和域名,@ .是固定符号)。
  • 匹配日期(yyyy-mm-dd):^\d{4}-\d{2}-\d{2}$(年份 4 位,月份和日期各 2 位,用 - 分隔)。

关键原则

  • 正则匹配是贪婪的(默认尽可能匹配最长的子串),加 ? 可改为非贪婪(如 a.*?b 匹配最短的 a 到 b 之间的内容)。
  • 特殊字符需转义(如匹配 \ 需写为 \,Java 中需写为 \\,因为字符串本身也需要转义)。

二、Matcher 类的核心方法#

Matcher 类提供了三个主要方法用于执行匹配操作:

  1. matches()
    • 功能:尝试将整个输入字符串与正则表达式匹配
    • 返回值:完全匹配返回 true,否则返回 false
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("12345");
System.out.println(matcher.matches()); // true
matcher = pattern.matcher("123abc");
System.out.println(matcher.matches()); // false
  1. find()
    • 功能:在输入字符串中查找下一个匹配的子序列
    • 返回值:找到匹配返回 true,否则返回 false
    • 特点:可多次调用,用于查找所有匹配项
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("abc123def456");
while (matcher.find()) {
System.out.println("匹配到: " + matcher.group());
}
// 输出:
// 匹配到: 123
// 匹配到: 456
  1. lookingAt()
    • 功能:从输入字符串的开始位置尝试匹配正则表达式
    • 返回值:如果字符串的前缀匹配模式,返回 true,否则 false
    • 与 matches() 的区别:不要求整个字符串匹配,只检查前缀
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("123abc");
System.out.println(matcher.lookingAt()); // true(前缀"123"匹配)
System.out.println(matcher.matches()); // false(整个字符串不匹配)

常用函数

  • split() 参数为”str” 以str划分
  • replace(a,b) 用b代替句子中的a
"],\\s*\\["代表着: [在java中有特殊含义,需要加入\\进行转义 \\s*匹配任意长度的空白字符
arrStr.replaceAll("^\\[|\\]$", ""):代表着使用""代替任何[或者] ^代表开头,$代表结尾
\" "代表着:进行转义
正则 ^1\\d{10}$ 表示:^ 开头,1 第一个字符是 1,\\d{10} 后跟 10 位数字,$ 结尾(确保整个字符串长度为 11 位)。

在 Java 中,replace、replaceAll 和 replaceFirst 是字符串类中用于替换的三个方法,它们的主要区别在于匹配规则和替换逻辑,具体如下:

  1. replace(CharSequence target, CharSequence replacement)
  • 作用:将字符串中所有与 target 完全匹配的子串,替换为 replacement。
  • 匹配规则:基于字面量匹配(即严格的字符序列匹配,不是正则表达式)。
示例:
String s = "aabbaabbaa";
String result = s.replace("aa", "XX");
System.out.println(result); // 输出:XXbbaXXbbaa
这里 aa 是字面量,所有连续的 aa 都会被替换为 XX。
  1. replaceAll(String regex, String replacement)
  • 作用:将字符串中所有与正则表达式 regex 匹配的子串,替换为 replacement。
  • 匹配规则:基于正则表达式匹配(支持复杂的模式匹配,如 \d 匹配数字、[a-z] 匹配小写字母等)。
  • 注意:正则中的特殊字符(如 .、*、+ 等)需要转义(用 \)。
示例:
String s = "a1b2c3d4";
String result = s.replaceAll("\\d", "X"); // 正则 \d 匹配数字
System.out.println(result); // 输出:aXbXcXdX
这里 \d 是正则表达式,所有数字都会被替换为 X
  1. replaceFirst(String regex, String replacement)
  • 作用:将字符串中第一个与正则表达式 regex 匹配的子串,替换为 replacement。
  • 匹配规则:基于正则表达式匹配(与 replaceAll 规则相同),但仅替换第一个匹配项。
示例:
String s = "a1b2c3d4";
String result = s.replaceFirst("\\d", "X");
System.out.println(result); // 输出:aXb2c3d4
这里仅第一个数字 1 被替换为 X。

核心区别总结

方法匹配规则替换范围典型场景
replace字面量匹配所有匹配项固定子串替换(如替换特定单词)
replaceAll正则表达式匹配所有匹配项复杂模式替换(如替换所有数字)
replaceFirst正则表达式匹配第一个匹配项仅替换首次出现的模式

如果需要简单的字面量替换,用 replace;如果需要正则表达式的灵活匹配,则用 replaceAll 或 replaceFirst(根据是否仅替换第一个匹配项选择)。

正则表达式
https://www.fdssong.js.cn/posts/正则表达式/
作者
FDSSONG
发布于
2025-11-03
许可协议
CC BY-NC-SA 4.0