文章目录
- [444. Java 正则表达式 - 捕获组与反向引用](#444. Java 正则表达式 - 捕获组与反向引用)
-
- [1. 什么是捕获组? 🧩](#1. 什么是捕获组? 🧩)
- [2. 捕获组的编号规则 🔢](#2. 捕获组的编号规则 🔢)
-
- [在 Java 中如何查看捕获组?](#在 Java 中如何查看捕获组?)
- [示例 🧪](#示例 🧪)
- [3. 反向引用 (Backreferences) 🔄](#3. 反向引用 (Backreferences) 🔄)
-
- [示例 1:匹配连续重复的数字](#示例 1:匹配连续重复的数字)
- [示例 2:匹配相同单词](#示例 2:匹配相同单词)
- [示例 3:嵌套组也能反向引用](#示例 3:嵌套组也能反向引用)
- [4. 非捕获组 (Non-Capturing Groups) 🙅♂️](#4. 非捕获组 (Non-Capturing Groups) 🙅♂️)
- [5. 小结 ✨](#5. 小结 ✨)
- [6. 课堂练习 🎤](#6. 课堂练习 🎤)
444. Java 正则表达式 - 捕获组与反向引用
大家好 🚀,今天我们继续深入学习正则表达式,重点是 捕获组 (Capturing Groups) 和 反向引用 (Backreferences)。
1. 什么是捕获组? 🧩
捕获组的作用:
👉 把一串字符 当作一个整体 来处理。
写法:用 () 括起来。
java
(dog)
这就表示一个组,包含 "dog" 三个字符。
匹配时,Java 会把这个组匹配到的内容保存起来,方便后面通过 反向引用 重新使用。
2. 捕获组的编号规则 🔢
捕获组是从 左到右 数开括号 ( 的顺序来编号的。
例如:
java
((A)(B(C)))
这里有 4 个捕获组:
1️⃣ ((A)(B(C))) → 最外层大括号
2️⃣ (A)
3️⃣ (B(C))
4️⃣ (C)
在 Java 中如何查看捕获组?
Matcher 提供了一些方法:
java
matcher.groupCount(); // 捕获组的总数(不包括 group 0)
matcher.group(0); // 整个正则匹配到的内容
matcher.group(1); // 第1个捕获组
matcher.start(1); // 捕获组1的起始位置
matcher.end(1); // 捕获组1的结束位置
👉 注意:
- group(0) → 总是代表整个正则表达式的匹配结果
- group(1) ~ group(n) → 依次代表括号里的捕获组
示例 🧪
java
import java.util.regex.*;
public class CapturingGroupsDemo {
public static void main(String[] args) {
String input = "abc123xyz";
String regex = "(abc)(\\d+)(xyz)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Group count = " + matcher.groupCount());
System.out.println("Group 0 = " + matcher.group(0)); // abc123xyz
System.out.println("Group 1 = " + matcher.group(1)); // abc
System.out.println("Group 2 = " + matcher.group(2)); // 123
System.out.println("Group 3 = " + matcher.group(3)); // xyz
}
}
}
运行结果:
java
Group count = 3
Group 0 = abc123xyz
Group 1 = abc
Group 2 = 123
Group 3 = xyz
3. 反向引用 (Backreferences) 🔄
捕获组匹配的内容会被保存,之后可以通过 \1, \2 ... 来引用。
\1→ 引用第1个捕获组\2→ 引用第2个捕获组- 依此类推
示例 1:匹配连续重复的数字
java
(\d\d)\1
含义:
(\d\d)→ 匹配两个数字(第1组)\1→ 再次匹配刚刚捕获到的两个数字
测试:
java
输入:1212 ✅ 匹配
输入:1234 ❌ 不匹配
示例 2:匹配相同单词
java
(\w+)\s\1
含义:
(\w+)→ 匹配一个单词(第1组)\s→ 匹配一个空格\1→ 再匹配前面那个单词
测试:
java
输入:hello hello ✅ 匹配
输入:hello world ❌ 不匹配
示例 3:嵌套组也能反向引用
java
(A(B(C)))
- group(1) =
ABC - group(2) =
BC - group(3) =
C
如果写 (A(B(C)))\2
→ 先匹配 "ABC",然后再匹配 "BC"。
4. 非捕获组 (Non-Capturing Groups) 🙅♂️
有时候我们只想用括号分组,但不想保存内容,这时可以用:
java
(?:...)
示例:
java
(?:dog|cat){2}
表示 "dog" 或 "cat",重复两次,但不会保存组内容。
5. 小结 ✨
()→ 捕获组,自动编号group(0)→ 整体匹配group(n)→ 第 n 个捕获组\n→ 反向引用第 n 个捕获组(?:...)→ 非捕获组
6. 课堂练习 🎤
- 写一个正则,匹配
"abab"这种模式(重复的"ab")。
👉 提示:(ab)\1 - 匹配重复单词(如
"bye bye")。
👉 提示:(\w+)\s\1 - 用非捕获组写一个正则,匹配
"dogdogcatcat"。
👉 提示:(?:dog|cat){2,}