Java正则表达式中 \\1 和 $1 的使用场景
1. 根本区别
| 语法 | 使用场景 | 作用 | 示例 |
|---|---|---|---|
\\1 | 正则表达式模式中 | 反向引用已匹配的捕获组 | "(a)\\1" 匹配 “aa” |
$1 | 替换字符串中 | 引用匹配到的捕获组 | replaceAll("(a)", "$1$1") |
2. \\1 - 正则表达式模式中的反向引用
基本用法
public class BackreferenceInPattern {
public static void main(String[] args) {
String[] testCases = {
"abab", // 匹配 - 重复 "ab"
"abcd", // 不匹配
"1111", // 匹配 - 重复 "11"
"aabb", // 匹配 - 重复 "aa" 和 "bb"
};
// \\1 引用第一个捕获组匹配的内容
String regex = "(\\w{2})\\1"; // 匹配重复的两位字符
Pattern pattern = Pattern.compile(regex);
for (String test : testCases) {
Matcher matcher = pattern.matcher(test);
//格式化参数
System.out.printf("'%s' %s匹配模式 %s%n",
test,
matcher.find() ? "【ok】" : "【no】",
regex);
}
}
}
输出:
'abab' 【ok】匹配模式 (\w{2})\1
'abcd' 【no】匹配模式 (\w{2})\1
'1111' 【ok】匹配模式 (\w{2})\1
'aabb' 【ok】匹配模式 (\w{2})\1
复杂反向引用示例
public class ComplexBackreference {
public static void main(String[] args) {
// 匹配重复的单词
String text = "hello hello world world java java programming";
String regex = "\\b(\\w+)\\s+\\1\\b"; // \\1 引用前面匹配的单词
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
System.out.println("找到的重复单词:");
while (matcher.find()) {
System.out.println("'" + matcher.group(1) + "' 重复出现在: '" + matcher.group() + "'");
}
// 匹配HTML标签对
String html = "<div>content</div> <p>text</p> <span>hello</span>";
String tagRegex = "<(\\w+)>[^<]+</\\1>"; // \\1 确保开始和结束标签相同
System.out.println("\n匹配的HTML标签对:");
Pattern tagPattern = Pattern.compile(tagRegex);
Matcher tagMatcher = tagPattern.matcher(html);
while (tagMatcher.find()) {
System.out.println("标签: " + tagMatcher.group(1) + ", 内容: " + tagMatcher.group());
}
}
}
3. $1 - 替换字符串中的引用
基本用法
public class DollarInReplacement {
public static void main(String[] args) {
String input = "John Smith (25) from New York";
// 重新排列信息
String rearranged = input.replaceAll("(\\w+)\\s+(\\w+)\\s+\\((\\d+)\\)\\s+from\\s+(.+)",
"$2, $1 (Age: $3) - $4");
System.out.println("重新排列: " + rearranged);
// 格式化电话号码
String phone = "13800138000";
String formattedPhone = phone.replaceAll("(\\d{3})(\\d{4})(\\d{4})", "$1-$2-$3");
System.out.println("格式化电话: " + formattedPhone);
// 日期格式转换
String date = "2023-12-25";
String usDate = date.replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$2/$3/$1");
//如果是中式日期,直接用/替换,可如果我是美式日期呢,这个使用场景不就体现了吗
System.out.println("美式日期: " + usDate);
}
}
在 appendReplacement 中使用 $1
public class DollarInAppendReplacement {
public static void main(String[] args) {
String text = "价格: $25.99, 重量: 2.5kg, 数量: 10个";
String regex = "([$¥]?)(\\d+(?:\\.\\d+)?)([a-zA-Z个件]*)\\b";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
// 使用 $1, $2, $3 引用捕获组
String replacement;
if ("$".equals(matcher.group(1))) {
replacement = "[美元: " + matcher.group(2) + "]";
} else if ("¥".equals(matcher.group(1))) {
replacement = "[人民币: " + matcher.group(2) + "]";
} else {
replacement = "[数值: " + matcher.group(2) + matcher.group(3) + "]";
}
matcher.appendReplacement(result, replacement);
}
matcher.appendTail(result);
System.out.println("原始: " + text);
System.out.println("替换后: " + result.toString());
}
}
4. 对比示例:相同需求的不同实现
public class CompareBackreferenceAndReplacement {
public static void main(String[] args) {
String input = "abc123def456";
System.out.println("=== 场景1: 查找重复字符 ===");
// 使用 \\1 在模式中查找重复
findRepeatedCharacters(input);
System.out.println("\n=== 场景2: 复制匹配内容 ===");
// 使用 $1 在替换中复制内容
duplicateMatchedContent(input);
System.out.println("\n=== 场景3: 交换内容 ===");
// 使用 $1, $2 等交换内容
swapContent("firstName lastName");
}
static void findRepeatedCharacters(String input) {
// 使用 \\1 在正则表达式模式中
String regex = "(\\w)\\1"; // 查找连续重复的字符
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
System.out.println("在 '" + input + "' 中查找重复字符:");
while (matcher.find()) {
System.out.println("找到重复字符 '" + matcher.group(1) + "' 在: " + matcher.group());
}
}
static void duplicateMatchedContent(String input) {
// 使用 $1 在替换字符串中
String duplicated = input.replaceAll("(\\d+)", "$1$1"); // 复制数字
System.out.println("复制数字后: " + duplicated);
String emphasized = input.replaceAll("(\\w+)", "**$1**"); // 强调所有单词
System.out.println("强调单词: " + emphasized);
}
static void swapContent(String input) {
// 使用 $1, $2 交换姓名顺序
String swapped = input.replaceAll("(\\w+)\\s+(\\w+)", "$2, $1");
System.out.println("姓名交换: '" + input + "' → '" + swapped + "'");
// 更复杂的重组
String complex = "2023年12月25日";
String reformed = complex.replaceAll("(\\d+)年(\\d+)月(\\d+)日", "$1-$2-$3");
System.out.println("日期重组: '" + complex + "' → '" + reformed + "'");
}
}
5. 高级用法:嵌套和多重引用
public class AdvancedReferences {
public static void main(String[] args) {
// 多重反向引用
String text = "abcabc123123xyzxyz";
String regex = "(\\w+)(\\d+)\\1\\2"; // \\1 引用单词, \\2 引用数字
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
System.out.println("多重反向引用匹配:");
while (matcher.find()) {
System.out.println("完整匹配: " + matcher.group());
System.out.println("单词部分: " + matcher.group(1));
System.out.println("数字部分: " + matcher.group(2));
}
// 复杂替换
String data = "name=John,age=25,city=New York";
String sql = data.replaceAll("(\\w+)=([^,]+)", "$1='$2'");
System.out.println("\nSQL格式: " + sql);
// 使用 appendReplacement 的复杂替换
StringBuffer buffer = new StringBuffer();
Matcher m = Pattern.compile("(\\w+)=([^,]+)").matcher(data);
while (m.find()) {
String key = m.group(1);
String value = m.group(2);
// 根据不同的键进行不同的替换
String replacement = switch (key) {
case "name" -> "姓名: " + value;
case "age" -> "年龄: " + value;
case "city" -> "城市: " + value;
default -> key + ": " + value;
};
m.appendReplacement(buffer, replacement);
}
m.appendTail(buffer);
System.out.println("格式化数据: " + buffer.toString());
}
}
6. 常见错误和注意事项
public class CommonMistakes {
public static void main(String[] args) {
String input = "hello world";
// 错误1: 在模式中使用 $1
try {
String wrongRegex = "(\\w+) $1"; // 错误! 应该在模式中使用 \\1
Pattern.compile(wrongRegex);
} catch (Exception e) {
System.out.println("错误1: " + e.getMessage());
}
// 错误2: 在替换中使用 \\1
String wrongReplacement = input.replaceAll("(\\w+)", "\\\\1"); // 错误! 应该使用 $1
System.out.println("错误替换结果: " + wrongReplacement);
// 正确用法
String correct1 = input.replaceAll("(\\w+) \\1", "REPEATED"); // 模式中用 \\1
String correct2 = input.replaceAll("(\\w+)", "$1$1"); // 替换中用 $1
System.out.println("正确结果1: " + correct1);
System.out.println("正确结果2: " + correct2);
// 转义注意事项
System.out.println("\n=== 转义示例 ===");
String withDollar = "价格: $100";
// 要在替换中得到字面 $,需要转义
String escaped = withDollar.replaceAll("\\$(\\d+)", "\\\\$$1"); // 得到: 价格: \$100
System.out.println("转义结果: " + escaped);
}
}
关键总结
\\1 的使用场景:
- 在正则表达式模式中
- 用于匹配时引用前面已匹配的捕获组
- 示例:
"(ab)\\1"匹配 “abab”
$1 的使用场景:
- 在替换字符串中
- 用于替换时引用匹配到的捕获组
- 示例:
replaceAll("(a)", "$1$1")把 “a” 替换为 “aa”
简单记忆:
- 模式中用
\\1,\\2,\\3…(双反斜杠) - 替换中用
$1,$2,$3…(美元符号) - 两者编号都从 1 开始,
\\0或$0表示整个匹配
795

被折叠的 条评论
为什么被折叠?



