Java 正则表达式 详解

Java 正则表达式详解

一、正则表达式基础

正则表达式(Regular Expression,简称 Regex)是一种描述字符串模式的工具,用于搜索、匹配和操作文本。在 Java 中,主要通过 java.util.regex 包中的 PatternMatcher 类实现正则表达式功能。

二、正则表达式语法

  1. 元字符
  • .:匹配除换行符以外的任意单个字符。
  • ^:匹配输入字符串的开始位置。
  • $:匹配输入字符串的结束位置。
  • *:匹配前面的子表达式零次或多次。
  • +:匹配前面的子表达式一次或多次。
  • ?:匹配前面的子表达式零次或一次。
  • {n}:匹配前面的子表达式恰好 n 次。
  • {n,}:匹配前面的子表达式至少 n 次。
  • {n,m}:匹配前面的子表达式至少 n 次,至多 m 次。
  1. 字符类
  • [abc]:匹配 a、b 或 c 中的任意一个字符。
  • [^abc]:匹配除 a、b、c 外的任意一个字符。
  • [a-z]:匹配小写字母 a 到 z。
  • [A-Z]:匹配大写字母 A 到 Z。
  • [0-9]:匹配数字 0 到 9。
  • [a-zA-Z0-9]:匹配字母或数字。
  1. 预定义字符集
  • \\d:匹配一个数字字符,等价于 [0-9]
  • \\D:匹配一个非数字字符,等价于 [^0-9]
  • \\s:匹配任何空白字符,包括空格、制表符、换页符等。
  • \\S:匹配任何非空白字符。
  • \\w:匹配包括下划线的任何字母、数字或下划线字符,等价于 [a-zA-Z0-9_]
  • \\W:匹配任何非单词字符。
  1. 边界匹配
  • \\b:匹配单词边界,即单词字符(如字母、数字或下划线)和非单词字符之间的位置。
  • \\B:匹配非单词边界。
  1. 分组与捕获
  • ():捕获括号内的表达式,形成一个分组。
  • |:匹配左边或右边的表达式。
  1. 转义字符
  • \\:用于转义特殊字符,使其失去特殊含义。在 Java 中,正则表达式中的反斜杠需要写成 \\\\,因为 Java 字符串本身也需要转义。

三、Java 中的正则表达式类

  1. Pattern
  • 表示编译后的正则表达式模式。
  • 没有公共构造方法,需通过静态方法 compile(String regex) 编译正则表达式。
  • 示例:
    java Pattern pattern = Pattern.compile("\\d+"); // 编译匹配一个或多个数字的正则表达式
  1. Matcher
  • 用于对输入字符串进行匹配操作。
  • 通过调用 Pattern 对象的 matcher(CharSequence input) 方法获取 Matcher 对象。
  • 常用方法:
    • find():尝试在输入字符串中查找下一个匹配的子字符串。
    • matches():尝试将整个输入字符串与正则表达式进行匹配。
    • group():返回上一次匹配操作所匹配的子字符串。
    • replaceAll(String replacement):将输入字符串中所有匹配的子字符串替换为指定的字符串。
  • 示例:
    java Matcher matcher = pattern.matcher("abc123def456ghi"); while (matcher.find()) { System.out.println("找到匹配项: " + matcher.group()); // 输出: 找到匹配项: 123 找到匹配项: 456 }

四、正则表达式在 Java 中的常见应用

  1. 验证格式
  • 邮箱验证
    java String regex = "^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,}$"; String email = "test@example.com"; boolean isValid = email.matches(regex); // true
  • 电话号码验证
    java String regex = "^\\d{3}-\\d{3}-\\d{4}$"; String phone = "123-456-7890"; boolean isValid = phone.matches(regex); // true
  1. 提取信息
  • 提取数字
    java String text = "订单123,金额456.78元"; Pattern pattern = Pattern.compile("\\d+\\.?\\d*"); Matcher matcher = pattern.matcher(text); while (matcher.find()) { System.out.println("找到数字: " + matcher.group()); // 输出: 找到数字: 123 找到数字: 456.78 }
  1. 替换文本
  • 日期格式转换
    java String text = "2023-05-15"; String newText = text.replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$2/$3/$1"); // 结果: "05/15/2023"
  1. 分割字符串
  • 按数字分割
    java Pattern pattern = Pattern.compile("\\d+"); String input = "abc123def456ghi"; String[] parts = pattern.split(input); // 结果: ["abc", "def", "ghi"]

五、正则表达式优化技巧

  1. 使用非贪婪匹配
  • 贪婪匹配会尽可能多地匹配字符,而非贪婪匹配则尽可能少地匹配字符。
  • 示例:
    • 贪婪匹配:<.*>(匹配 <html>...</html> 为一个整体)
    • 非贪婪匹配:<.*?>(匹配 <html></html> 分别)
  1. 使用字符类和预定义字符集
  • 字符类(如 [a-z])和预定义字符集(如 \\d)比使用单独的字符或字符串更高效。
  • 示例:
    • 高效:\\d{3}-\\d{2}-\\d{4}
    • 低效:[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]
  1. 减少回溯
  • 复杂的正则表达式可能导致大量的回溯,特别是当表达式中包含多个嵌套量词时。减少回溯可以显著提高匹配效率。
  • 示例:
    • 低效:(a+)+b
    • 高效:a+b
  1. 编译正则表达式
  • 将正则表达式编译为 Pattern 对象,并重用它,而不是每次匹配时都编译。
  • 示例:
    java Pattern pattern = Pattern.compile("\\b\\w+\\b"); // 编译一次 Matcher matcher = pattern.matcher("Some text here."); while (matcher.find()) { System.out.println("Found word: " + matcher.group()); }
  1. 使用 String 类的内置方法
  • 对于一些简单的匹配任务,String 类的内置方法(如 contains()startsWith()endsWith())通常比正则表达式更高效。
  • 示例:
    java String text = "Hello, world!"; boolean containsWorld = text.contains("world"); // true

六、正则表达式示例代码

  1. 验证用户名
  • 用户名规则:长度 3-15,由字母、数字、下划线、连字符组成。
  • 正则表达式:^[a-z0-9_-]{3,15}$
  • 示例:
    java String regex = "^[a-z0-9_-]{3,15}$"; String username = "user_name-123"; boolean isValid = username.matches(regex); // true
  1. 验证密码
  • 密码规则:长度 6-20,包含至少一个数字、一个小写字母、一个大写字母和一个特殊字符(如 @#$%)。
  • 正则表达式:((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})
  • 示例:
    java String regex = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})"; String password = "Pass@123"; boolean isValid = password.matches(regex); // true
  1. 提取 HTML 链接
  • 示例:
    java String html = "<html><body><a href='https://example.com'>Example</a></body></html>"; String regex = "href=['\"](.*?)['\"]"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(html); while (matcher.find()) { System.out.println(matcher.group(1)); // 输出: https://example.com }

七、总结

  1. 正则表达式是 Java 中用于模式匹配和字符串处理的强大工具
  2. 核心类
  • Pattern:编译正则表达式。
  • Matcher:执行匹配操作。
  1. 常见应用
  • 验证格式(如邮箱、电话号码)。
  • 提取信息(如数字、链接)。
  • 替换文本(如日期格式转换)。
  • 分割字符串(如按数字分割)。
  1. 优化技巧
  • 使用非贪婪匹配。
  • 使用字符类和预定义字符集。
  • 减少回溯。
  • 编译正则表达式并重用。
  • 对于简单任务,使用 String 类的内置方法。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注