java.util.regex 包介绍

java.util.regex 包介绍

java.util.regex 是 Java 提供的正则表达式(Regular Expression)处理包,主要用于字符串的模式匹配、查找、替换等操作。它包含两个核心类:

  1. Pattern - 编译正则表达式
  2. Matcher - 执行匹配操作

1. 核心类

(1) Pattern(正则表达式编译)

  • 用于编译正则表达式,生成 Pattern 对象。
  • 线程安全,适合复用。
主要方法
方法说明
static Pattern compile(String regex)编译正则表达式
Matcher matcher(CharSequence input)创建 Matcher 对象
static boolean matches(String regex, CharSequence input)直接匹配(简化版)
String pattern()返回正则表达式字符串
示例
Pattern pattern = Pattern.compile("a*b"); // 编译正则表达式
Matcher matcher = pattern.matcher("aaab"); // 创建 Matcher
boolean isMatch = matcher.matches(); // true

(2) Matcher(匹配操作)

  • 用于对字符串进行匹配、查找、替换等操作。
主要方法
方法说明
boolean matches()整个字符串是否匹配
boolean find()查找下一个匹配的子串
String group()返回匹配的子串
int start(), int end()返回匹配的起始/结束索引
String replaceAll(String replacement)替换所有匹配的子串
String replaceFirst(String replacement)替换第一个匹配的子串
示例
Pattern pattern = Pattern.compile("\\d+"); // 匹配数字
Matcher matcher = pattern.matcher("abc123xyz456");

while (matcher.find()) {
    System.out.println("找到数字: " + matcher.group());
}

输出:

找到数字: 123
找到数字: 456

2. 常用正则表达式语法

表达式说明
\d数字 [0-9]
\D非数字 [^0-9]
\w单词字符 [a-zA-Z0-9_]
\W非单词字符
\s空白字符(空格、制表符等)
\S非空白字符
.任意字符(除换行符 \n
*0 次或多次
+1 次或多次
?0 次或 1 次
{n}恰好 n 次
{n,}至少 n 次
{n,m}n 到 m 次
^字符串开头
$字符串结尾
[abc]匹配 a、b 或 c
[^abc]不匹配 a、b、c
`(ab)`

3. 常见应用场景

(1) 验证字符串格式

// 验证手机号(11位数字)
String phone = "13800138000";
boolean isValid = phone.matches("\\d{11}"); // true

// 验证邮箱
String email = "test@example.com";
boolean isEmail = email.matches("\\w+@\\w+\\.\\w+"); // true

(2) 查找字符串中的数字

Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("价格: 99元, 折扣: 20%");

while (matcher.find()) {
    System.out.println("数字: " + matcher.group());
}

输出:

数字: 99
数字: 20

(3) 替换字符串

String text = "Java 8, Java 11, Java 17";
String updated = text.replaceAll("Java \\d+", "JDK"); // "JDK, JDK, JDK"

(4) 提取分组

// 提取日期(年、月、日)
String dateStr = "2023-10-25";
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(dateStr);

if (matcher.matches()) {
    String year = matcher.group(1);  // 2023
    String month = matcher.group(2); // 10
    String day = matcher.group(3);   // 25
}

4. 注意事项

  1. 转义字符:在 Java 字符串中,\ 需要写成 \\,如 \\d 表示 \d
  2. 性能优化
    • 多次使用同一个正则表达式时,预编译 Pattern 以提高性能。
    • 避免在循环中重复编译正则表达式。
  3. 贪婪匹配 vs 非贪婪匹配
    • .*(贪婪匹配,尽可能匹配更多字符)
    • .*?(非贪婪匹配,尽可能匹配更少字符)
  4. 线程安全
    • Pattern 是线程安全的,可以复用。
    • Matcher 不是线程安全的,每个线程应该有自己的 Matcher

5. 完整示例

import java.util.regex.*;

public class RegexExample {
    public static void main(String[] args) {
        // 1. 验证手机号
        String phone = "13800138000";
        boolean isPhoneValid = phone.matches("\\d{11}");
        System.out.println("手机号是否有效: " + isPhoneValid); // true

        // 2. 查找所有数字
        Pattern numberPattern = Pattern.compile("\\d+");
        Matcher numberMatcher = numberPattern.matcher("价格: 99元, 折扣: 20%");
        while (numberMatcher.find()) {
            System.out.println("找到数字: " + numberMatcher.group());
        }

        // 3. 替换字符串
        String text = "Java 8, Java 11, Java 17";
        String updatedText = text.replaceAll("Java \\d+", "JDK");
        System.out.println(updatedText); // JDK, JDK, JDK

        // 4. 提取分组(年-月-日)
        String dateStr = "2023-10-25";
        Pattern datePattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher dateMatcher = datePattern.matcher(dateStr);
        if (dateMatcher.matches()) {
            System.out.println("年: " + dateMatcher.group(1));
            System.out.println("月: " + dateMatcher.group(2));
            System.out.println("日: " + dateMatcher.group(3));
        }
    }
}

6. 总结

  • Pattern:编译正则表达式,生成可复用的匹配模式。
  • Matcher:执行匹配、查找、替换等操作。
  • 常见用途
    • 数据验证(邮箱、手机号、日期)
    • 字符串查找(提取数字、URL、关键词)
    • 字符串替换(批量修改文本)
    • 分组提取(解析结构化数据)

掌握 java.util.regex 可以让你更高效地处理字符串! 🚀

<think>我们正在处理一个正则表达式错误:`PatternSyntaxException: Illegal repetition near index 1`,并且错误的正则表达式是`^.{GCBH}`。 错误原因分析: 1. 在正则表达式中,`{`和`}`用于指定重复次数,例如`a{3}`表示匹配3个a。但是,在`^.{GCBH}`中,`{GCBH}`不是合法的重复语法,因为花括号内的内容必须是数字或者数字范围(如`{3}`, `{3,5}`),或者是某些特定的模式(如`{n}`, `{n,}`, `{n,m}`)。这里出现了字母,所以会抛出非法重复(Illegal repetition)的异常。 2. 用户意图可能是:用变量`GCBH`的值(即字符串"S186701S")作为要匹配的前缀,然后替换掉。但是,在正则表达式中,我们无法直接将一个变量放入模式中,除非我们进行字符串拼接。而且,这里用户还使用了`^.{GCBH}`,这显然不是正确的用法。 3. 实际上,用户可能想要删除字符串`TH`中开头部分等于`GCBH`字符串的内容。注意,`GCBH`的值是"S186701S",而`TH`的值是"S186701S-T0101",所以用户可能想删除开头的"S186701S",得到"-T0101"。 但是,当前的正则表达式写法是完全错误的。 解决方案: 我们应该使用正确的正则表达式,并且注意,如果我们要匹配一个固定的字符串(即字面量),我们应该使用`Pattern.quote`来转义任何可能被解释为正则元字符的字符。但是,这里我们不需要使用量词,而是直接匹配整个字符串。 因此,我们可以这样写: ```java String GCBH = "S186701S"; String TH = "S186701S-T0101"; // 我们想要删除开头的GCBH字符串,注意:如果TH不是以GCBH开头,则不会替换 String X = TH.replaceFirst("^" + Pattern.quote(GCBH), ""); ``` 解释: - `replaceFirst`用于替换第一个匹配项(因为我们只需要匹配开头)。 - `^`表示字符串的开头。 - `Pattern.quote(GCBH)`将字符串`GCBH`中的特殊字符转义,使其作为字面量处理。例如,如果`GCBH`中含点(.)或星号(*)等,它们不会被解释为正则元字符。 但是,注意:在原始代码中,用户使用了`replaceAll`,但我们这里使用`replaceFirst`,因为只需要匹配一次(在开头)。当然,也可以使用`replaceAll`,但需要确保只匹配开头一次,所以`replaceFirst`更合适。 如果用户确实想用正则表达式,并且`GCBH`字符串中不含正则特殊字符,也可以直接拼接: ```java String X = TH.replaceFirst("^" + GCBH, ""); ``` 但是,为了安全起见,使用`Pattern.quote`是更好的做法。 另外,如果用户不想使用正则表达式,也可以使用字符串操作: ```java if (TH.startsWith(GCBH)) { String X = TH.substring(GCBH.length()); } else { String X = TH; } ``` 这样更直接,且没有正则表达式的复杂性和潜在错误。 根据用户提供的错误信息,我们得知错误是因为在正则表达式中使用了非法重复(`{GCBH}`)。因此,修正的核心是避免这种非法的正则语法。 引用[1]和[3]都提到了`Illegal repetition`,这通常是因为在量词`{}`中使用了非数字的内容。而引用[2]则是一个Unicode属性错误,与本问题无关。 因此,我们给出两种解决方案: 1. 使用正则表达式(但正确拼接)并转义字面量。 2. 使用字符串操作(substring)。 推荐使用第二种,因为意图是删除固定前缀,使用字符串操作更简单高效。 代码示例: ```java String GCBH = "S186701S"; String TH = "S186701S-T0101"; String X; if (TH.startsWith(GCBH)) { X = TH.substring(GCBH.length()); } else { X = TH; // 如果不是以GCBH开头,则保持不变 } System.out.println(X); // 输出: -T0101 ``` 这样就不会出现正则表达式错误了。 相关问题: 1.Java中如何安全地使用字符串作为正则表达式模式? 2. 处理字符串前缀时,使用正则表达式和字符串操作哪个更好? 3. 如何避免`PatternSyntaxException`异常? 4. 在字符串替换中,`replace`、`replaceAll`和`replaceFirst`有什么区别?</think>针对 Java 正则表达式 `^.{GCBH}` 导致的 `PatternSyntaxException: Illegal repetition near index 1` 错误,以下是详细解决方案: ### 错误原因分析 1. **非法重复语法**: ```java TH.replaceAll("^.{GCBH}", ""); // 错误! ``` - `{GCBH}` 是非法正则量词,量词必须为数字格式(如 `{4}`)或范围(如 `{1,5}`) - Java 将 `{G` 视为非法重复语法触发异常[^1][^3] 2. **变量未正确引用**: - 意图可能是用变量 `GCBH` 的值("S186701S")作为匹配模式 - 但直接写入 `{GCBH}` 会被当作字面字符而非变量引用 --- ### 解决方案 #### 方案 1:正确使用变量(推荐) ```java String GCBH = "S186701S"; String TH = "S186701S-T0101"; // 转义特殊字符后拼接变量 String regex = "^" + Pattern.quote(GCBH); String X = TH.replaceFirst(regex, ""); System.out.println(X); // 输出: -T0101 ``` - **关键点**: - `Pattern.quote()` 转义变量中的正则特殊字符(如 `.` `*` 等)[^3] - 使用 `replaceFirst()` 替代 `replaceAll()` 更高效(只需匹配开头一次) #### 方案 2:固定长度匹配(若需通用前缀) ```java // 匹配开头9个字符(GCBH长度) String X = TH.replaceFirst("^.{9}", ""); ``` - 适用场景:当 `GCBH` 长度固定且无特殊字符时 #### 方案 3:非正则的字符串操作 ```java String X = TH.startsWith(GCBH) ? TH.substring(GCBH.length()) : TH; ``` - **优势**:完全避免正则,性能更高 - **输出**:`-T0101` --- ### 错误预防指南 | **错误写法** | **修复方案** | **原理** | |---------------------|----------------------------------|------------------------------| | `^.{GCBH}` | `^ + Pattern.quote(GCBH)` | 转义特殊字符并正确拼接变量 | | `{ABC}` | 改为数字量词如 `{3}` | 量词必须为数字 | | 未处理边界符 `^` | 添加 `(?m)` 启用多行模式 | 确保 `^` 匹配每行开头 | | 未处理元字符 `.` | 用 `\\.` 转义 | `.` 在正则中表示任意字符 | > **最佳实践**: > 使用 [Regex Tester](https://regex101.com/) 在线测试正则表达式,或添加异常处理: > ```java > try { > TH.replaceAll(regex, ""); > } catch (PatternSyntaxException e) { > System.err.println("正则错误: " + e.getMessage()); > } > ``` --- ### 根本问题解析 `Illegal repetition` 异常通常由以下原因触发: 1. **量词格式错误**:`{x}` 中 `x` 必须为整数 ```java // 错误示例:字母代替数字 "a{xyz}".matches("a{xyz}"); // 抛出 PatternSyntaxException[^1][^3] ``` 2. **特殊字符未转义**:如 `{` `}` `.` `*` 等未用反斜杠转义 ```java // 正确转义示例 "price: $5.99".replaceAll("\\$", "¥"); // 输出: price: ¥5.99 ``` 3. **Unicode 属性错误**:`\p{...}` 含无效属性名时触发 `Incorrect Unicode property`[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值