Java 正则表达式
- Java
- 7天前
- 38热度
- 0评论
1、Java使用正则表达式
java.util.regex 包是 Java 标准库中用于支持正则表达式操作的包。[1]
包括以下三个类:
- Pattern 类:
Pattern 对象是一个正则表达式的编译表示。调用 Pattern 对象的 compile 方法来获得一个 Pattern 对象。
如:Pattern pattern = Pattern.compile("[0-9]*"); - Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
如:Matcher isNum = pattern.matcher(str); - PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
1.1、matches() 判断字符串中是否匹配
字符串与正则表达式匹配,完全匹配:true,不完全匹配:false
// 1. 编译正则表达式,生成Pattern对象
Pattern pattern = Pattern.compile("a*b");
// 2. 创建Matcher对象,关联待匹配的字符串
Matcher matcher = pattern.matcher("aaaaab");
// 3. 执行匹配操作
boolean matchFound = matcher.matches();
System.out.println(matchFound); // 输出: true
1.2、find() 查找匹配项
查找匹配的元素
find():返回是否有找到
group():返回查找到的下一个
start():返回起始索引
end(): 返回结束索引
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("dde123eee456fff");
while (matcher.find()) {
System.out.println("找到:"+matcher.group()+", 开始位置:"+matcher.start()+",结束位置:"+matcher.end());
}
// 输出:
// 找到:123, 开始位置:3,结束位置:6
// 找到:456, 开始位置:9,结束位置:12
1.3、lookingAt() 前缀匹配模式
判断字符串是否以XX开头,是:true,否:false
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("123eee");
System.out.println(matcher.lookingAt());
//输出: true
2、正则表达式语法
元字符匹配[2]
| 字符 | 描述 |
| . | 匹配除换行符以外的任意字符 |
| ^ | 匹配字符串的开始位置 |
| $ | 匹配字符串的结束位置 |
| * | 匹配前面的子表达式零次或多次 |
| + | 匹配前面的子表达式一次或多次 |
| ? | 匹配前面的子表达式零次或一次 |
| {n} | 匹配前面的子表达式恰好n次 |
| {n,} | 匹配前面的子表达式至少n次 |
| {n,m} | 匹配前面的子表达式至少n次,至多m次 |
| [] | 匹配方括号中指定的任意一个字符 |
| [^] | 匹配不在方括号中指定的任意一个字符 |
| () | 标记一个子表达式的开始和结束位置 |
| | | 表示或关系,匹配两个或多个选项之一 |
预定义字符匹配
| 字符 | 表达式 | 描述 |
| \d | [0-9] | 匹配一个数字字符 |
| \D | [^0-9] | 匹配一个非数字字符 |
| \w | [a-zA-Z_0-9] | 匹配一个单词字符(字母、数字、下划线) |
| \W | [^a-zA-Z_0-9] | 匹配一个非单词字符 |
| \s | [ \t\n\x0B\f\r] | 匹配一个空白字符(空格、制表符、换行符等) |
| \S | [^ \t\n\x0B\f\r] | 匹配一个非空白字符 |
3、注意事项
- 复用Pattern对象
避免在循环中重复编译相同的正则表达式,应将编译后的Pattern对象缓存并复用。 - 优先使用String类的方法
对于简单的字符串操作,如startsWith()、endsWith()、indexOf()等,应优先使用String类的方法,比正则表达式效率更高。
4、常见案例
4.1、使用圆括号()分别提取
使用圆括号()可以将正则表达式中的部分内容分组,每个分组可以被单独捕获和引用。分组编号从1开始,0表示整个匹配结果。[2]
比如:分别提取邮箱的用户名和域名
public class GroupExample {
public static void main(String[] args) {
String email = "test.user@example.com";
String regex = "([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
if (matcher.matches()) {
System.out.println("完整匹配: " + matcher.group(0)); // 整个匹配结果
System.out.println("用户名: " + matcher.group(1)); // 第一组
System.out.println("域名: " + matcher.group(2)); // 第二组
}
}
}
//完整匹配: test.user@example.com
//用户名: test.user
//域名: example.com
4.2、贪婪匹配与非贪婪匹配
- 贪婪匹配
默认情况下,正则表达式的量词(如*、+、{n,m})是贪婪的,会尽可能多地匹配字符。例如,<.*> 会匹配整个 HTML 标签。 - 非贪婪匹配
在量词后面加上?,可以将贪婪匹配转换为非贪婪匹配,尽可能少地匹配字符。如 <.*?>,只匹配最短的内容。
public class GreedyVsNonGreedy {
public static void main(String[] args) {
String text = "<html><body><h1>Hello</h1></body></html>";
// 贪婪匹配
String greedyRegex = "<.*>";
Pattern greedyPattern = Pattern.compile(greedyRegex);
Matcher greedyMatcher = greedyPattern.matcher(text);
if (greedyMatcher.find()) {
System.out.println("贪婪匹配: " + greedyMatcher.group());
}
// 非贪婪匹配
String nonGreedyRegex = "<.*?>";
Pattern nonGreedyPattern = Pattern.compile(nonGreedyRegex);
Matcher nonGreedyMatcher = nonGreedyPattern.matcher(text);
while (nonGreedyMatcher.find()) {
System.out.println("非贪婪匹配: " + nonGreedyMatcher.group());
}
}
}
//输出:
贪婪匹配: <html><body><h1>Hello</h1></body></html>
非贪婪匹配: <html>
非贪婪匹配: <body>
非贪婪匹配: <h1>
非贪婪匹配: </h1>
非贪婪匹配: </body>
非贪婪匹配: </html>
4.3、断言
- (?=...) 正向前瞻
匹配后面跟着特定模式的地方,比如:a(?=b) 匹配 a,但要求其后必须是 b - (?!...) 负向前瞻
匹配后面不跟着特定模式的地方,比如:a(?!b) 匹配 a,但要求其后不跟 b
4.4、常见正则表达式
| 匹配 | 正则 |
| 邮箱 | ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$ |
| 身份证 | ^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$ |
| URL | ^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$ |
| 日期(YYYY-MM-DD) | ^\d{4}-\d{2}-\d{2}$ |
| IPv4地址 | ^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$ |
| HTML标签 | <([a-z]+)([^<]+)*(?:>(.*?)<\/\1>|\s*\/>) |
| 中文字符 | ^[\u4e00-\u9fa5]+$ |
| 邮政编码(中国) | ^\d{6}$ |
| 密码强度(8位且含字母和数字) | ^(?=.*\d)(?=.*[a-zA-Z]).{8,}$ |
| 正整数 | ^[1-9]\d*$ |
| 负整数 | ^-\d+$ |
| 整数 | ^-?[1-9]\d*$ |
| 整数(含前导零) | ^-?\d+$ |
| 小数 | ^-?(?:0|[1-9]\d*)\.\d+$ |
| 科学计数法 | ^-?\d+(?:\.\d+)?[eE][+-]?\d+$ |
| 简写小数(允许 .5 或 0.5 格式) | ^-?\d*\.?\d+$ |
[3]
