正则表达式(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); } }}
提取到的数字:9932972.正则表达式语法基础
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)
以下字符在正则中有特殊含义,需用反斜杠 \ 转义(如匹配 * 需写为 \*):
^ $ . * + ? ( ) [ ] { } | \
三、常用匹配规则
- 匹配任意字符:.
匹配除换行符(\n)外的任意单个字符。
示例:
正则 a.b 匹配 aab、acb、a1b(中间是任意字符),不匹配 ab(长度不够)、a\nb(含换行)
- 边界匹配:^ 和 $
- ^:匹配字符串的开头(如 ^abc 匹配以 abc 开头的字符串,如 abc123)。
- 匹配以 xyz 结尾的字符串,如 123xyz)。
示例:
正则 ^abc$ 仅匹配完整字符串 abc(精确匹配,常用于格式验证)。
- 重复匹配:*、+、?
- *:匹配前面的元素0 次或多次(尽可能多,贪婪模式)。
示例:a* 匹配 ""(空)、a、aa、aaa 等。
- +:匹配前面的元素1 次或多次。
示例:a+ 匹配 a、aa、aaa 等(至少 1 个 a)。
- ?:匹配前面的元素0 次或 1 次。
示例:a? 匹配 "" 或 a(最多 1 个 a)。
- 限定重复次数:{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 个)。 规则:
- 范围用 - 表示(如 [0-9] 匹配任意数字,[a-z] 匹配任意小写字母)。
- 否定用 ^ 表示(如 [^0-9] 匹配非数字字符)。
- 特殊字符在 [] 内无需转义(如 [.+] 直接匹配 .、、+)。
示例: [a-zA-Z0-9] 匹配任意字母或数字(类似 \w,见下文)。
- 预定义字符集(快捷写法)
| 语法 | 含义 | 等价写法 |
| \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] |
-
逻辑或:| 匹配 | 前后的任意一个模式。 示例: 正则 abc|def 匹配 abc 或 def(如 xyzabc 中的 abc,def123 中的 def)。
-
分组:( ) 将多个字符视为一个整体,可结合重复符号使用。 示例: (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 类提供了三个主要方法用于执行匹配操作:
- 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- find()
- 功能:在输入字符串中查找下一个匹配的子序列
- 返回值:找到匹配返回 true,否则返回 false
- 特点:可多次调用,用于查找所有匹配项
Pattern pattern = Pattern.compile("\\d+");Matcher matcher = pattern.matcher("abc123def456");
while (matcher.find()) { System.out.println("匹配到: " + matcher.group());}// 输出:// 匹配到: 123// 匹配到: 456- 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 是字符串类中用于替换的三个方法,它们的主要区别在于匹配规则和替换逻辑,具体如下:
- replace(CharSequence target, CharSequence replacement)
- 作用:将字符串中所有与 target 完全匹配的子串,替换为 replacement。
- 匹配规则:基于字面量匹配(即严格的字符序列匹配,不是正则表达式)。
示例:
String s = "aabbaabbaa";String result = s.replace("aa", "XX");System.out.println(result); // 输出:XXbbaXXbbaa
这里 aa 是字面量,所有连续的 aa 都会被替换为 XX。- 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- 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(根据是否仅替换第一个匹配项选择)。