《Java高级编程:从原理到实战 - 进阶知识篇二》
一. 正则表达式基础
1.1 基本概念
-
正则表达式:用于描述字符串模式的特殊语法
-
用途:字符串匹配、查找、替换、分割等操作
-
Java实现:
java.util.regex
包
1.2 核心类
-
Pattern:编译后的正则表达式模式(不可变、线程安全)
-
Matcher:通过解释Pattern对字符序列执行匹配操作的引擎
二. 正则表达式语法
2.1 字符匹配
表达式 | 说明 | 示例 |
---|---|---|
. | 匹配任意单个字符(除换行符) | a.c 匹配"abc" |
\d | 数字[0-9] | \d\d 匹配"12" |
\D | 非数字[^0-9] | \D 匹配"a" |
\w | 单词字符[a-zA-Z_0-9] | \w+ 匹配单词 |
\W | 非单词字符[^\w] | \W 匹配"@" |
\s | 空白字符[\t\n\x0B\f\r] | \s 匹配空格 |
\S | 非空白字符[^\s] | \S 匹配"a" |
2.2 数量限定符
表达式 | 说明 | 示例 |
---|---|---|
* | 0次或多次 | a*b 匹配"b","ab","aab" |
+ | 1次或多次 | a+b 匹配"ab","aab" |
? | 0次或1次 | a?b 匹配"b","ab" |
{n} | 恰好n次 | a{2} 匹配"aa" |
{n,} | 至少n次 | a{2,} 匹配"aa","aaa" |
{n,m} | n到m次 | a{2,4} 匹配"aa","aaa","aaaa" |
2.3 位置匹配
表达式 | 说明 | 示例 |
---|---|---|
^ | 行/字符串开始 | ^Java 匹配以"Java"开头的行 |
$ | 行/字符串结束 | end$ 匹配以"end"结尾的行 |
\b | 单词边界 | \bJava\b 匹配独立的"Java"单词 |
\B | 非单词边界 | \Bend\B 匹配"weekend"中的"end" |
2.4 分组与捕获
表达式 | 说明 | 示例 |
---|---|---|
(pattern) | 捕获分组 | (ab)+ 匹配"abab" |
(?:pattern) | 非捕获分组 | (?:ab)+ 匹配但不捕获 |
(?<name>pattern) | 命名捕获组 | (?<year>\d{4}) 捕获为year组 |
三. Java正则API使用
3.1 基本使用步骤
// 1. 编译正则表达式
Pattern pattern = Pattern.compile("正则表达式");// 2. 创建匹配器
Matcher matcher = pattern.matcher("输入字符串");// 3. 执行匹配操作
boolean isMatch = matcher.matches(); // 或find(), group()等
3.2 常用方法
方法 | 说明 |
---|---|
Pattern.compile(String regex) | 编译正则表达式 |
matcher(CharSequence input) | 创建匹配器 |
matches() | 尝试将整个区域与模式匹配 |
find() | 查找下一个匹配的子序列 |
group() | 返回前一次匹配的子序列 |
group(int group) | 返回指定捕获组匹配的子序列 |
start() /end() | 返回匹配的起始/结束索引 |
replaceAll(String replacement) | 替换所有匹配项 |
3.3 常用模式标志
标志 | 说明 |
---|---|
Pattern.CASE_INSENSITIVE | 不区分大小写匹配 |
Pattern.MULTILINE | 多行模式(^和$匹配行首行尾) |
Pattern.DOTALL | .匹配任何字符包括行终止符 |
Pattern.UNICODE_CASE | Unicode感知的大小写折叠 |
四. 常见应用示例
4.1 验证格式
// 验证邮箱
boolean isValidEmail = Pattern.matches("\\w+@\\w+\\.\\w+", "test@example.com");// 验证手机号(中国)
String phoneRegex = "1[3-9]\\d{9}";
boolean isValidPhone = "13812345678".matches(phoneRegex);
4.2 提取信息
Pattern datePattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = datePattern.matcher("2023-06-15");
if (matcher.find()) {String year = matcher.group(1); // "2023"String month = matcher.group(2); // "06"String day = matcher.group(3); // "15"
}
4.3 替换文本
String text = "foo123bar456baz";
String replaced = text.replaceAll("\\d+", "NUM"); // "fooNUMbarNUMbaz"
4.4 分割字符串
String[] parts = "one,two,three".split("\\s*,\\s*"); // ["one", "two", "three"]
五. 高级特性
5.1 零宽断言
表达式 | 说明 |
---|---|
(?=pattern) | 正向先行断言(后面跟着pattern) |
(?!pattern) | 负向先行断言(后面不跟pattern) |
(?<=pattern) | 正向后行断言(前面是pattern) |
(?<!pattern) | 负向后行断言(前面不是pattern) |
5.2 贪婪/懒惰/独占模式
模式 | 表示法 | 说明 |
---|---|---|
贪婪 | X* | 尽可能多匹配(默认) |
懒惰 | X*? | 尽可能少匹配 |
独占 | X*+ | 尽可能多匹配且不回溯 |
六. 性能优化建议
-
预编译Pattern:多次使用的正则表达式应该预编译
-
避免复杂回溯:减少嵌套的量词和或操作
-
使用非捕获组:不需要捕获时使用
(?:pattern)
-
合理使用边界:用
\b
等提高匹配效率 -
避免过度使用:简单字符串操作可用String方法替代