ava中的正则表达式是用于匹配、搜索和操作文本的强大工具。它们广泛应用于数据验证、文本解析和替换等场景。Java提供了java.util.regex
包,其中主要包含两个类:Pattern
和Matcher
,用于处理正则表达式。
下面将简单地讲解Java中的正则表达式,包括基础概念、语法、使用步骤和示例代码。
一. 什么是正则表达式
正则表达式(Regular Expression,简称regex)是一种用于匹配字符串模式的强大工具。
基础概念
- Pattern(模式):表示已编译的正则表达式。它是不可变的,可用于创建多个
Matcher
实例。 - Matcher(匹配器):用于执行匹配操作的引擎。它依赖于
Pattern
并应用到目标字符序列上。
它可以:
- 查找文本
- 替换文本
- 验证格式
- 提取字符串中的特定部分
二、正则表达式语法
1. 字符匹配
- 普通字符:直接匹配自身,如
a
匹配字符'a'
。 - 元字符:具有特殊含义的字符,如
.
、*
、+
、?
、^
、$
、[]
、{}
、()
等。
2. 字符类
[abc] // 匹配a、b或c中的任意一个字符
[^abc] // 匹配除了a、b、c以外的任意字符
[a-z] // 匹配所有小写字母
[A-Z] // 匹配所有大写字母
[0-9] // 匹配所有数字
3. 预定义字符类
.:匹配除换行符\n外的任意字符。
\d:匹配数字,等价于[0-9]。
\D:匹配非数字字符,等价于[^0-9]。
\s:匹配空白字符,包括空格、制表符等。
\S:匹配非空白字符。
\w:匹配字母、数字或下划线,等价于[a-zA-Z0-9_]。
\W:匹配非字母、数字或下划线字符。
4. 量词
* // 匹配前面的表达式0次或多次
+ // 匹配前面的表达式1次或多次
? // 匹配前面的表达式0次或1次
{n} // 匹配前面的表达式恰好n次
{n,} // 匹配前面的表达式至少n次
{n,m} // 匹配前面的表达式n到m次
三、基本使用步骤
1. 编译正则表达式
使用Pattern.compile()
方法编译正则表达式:
Pattern pattern = Pattern.compile("正则表达式");
2. 创建匹配器
使用pattern.matcher()
方法创建Matcher
对象:
Matcher matcher = pattern.matcher("目标字符串");
3. 进行匹配
使用Matcher
类的方法执行匹配操作:
matches()
:整个字符串是否匹配。find()
:查找下一个匹配的子字符串。group()
:获取当前匹配的子字符串。
四、示例代码
下面通过一个示例演示如何在Java中使用正则表达式。
1.验证邮箱地址
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class EmailValidator {
public static void main(String[] args) {
String email = "user@example.com";
String regex = "^[\\w.-]+@[\\w.-]+\\.\\w+$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(email);
if (matcher.matches()) {
System.out.println("邮箱地址有效");
} else {
System.out.println("邮箱地址无效");
}
}
}
2.提取数字
public class NumberExtractor {
public static void main(String[] args) {
String text = "订单编号:12345,金额:¥678.90";
String regex = "\\d+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println("找到的数字:" + matcher.group());
}
}
}
例题:根据给定菜单,输出菜单中价格数据,并计算出菜单中菜品的总价格
public class Menu {
public static void main(String[] args) {
// 示例菜单字符串
String menu = "红烧肉 28.8元\n" +
"清蒸鱼 38.5元\n" +
"炒青菜 12.5元\n" +
"蛋炒饭 16.0元\n" +
"番茄蛋汤 9.8元";
processMenu(menu);
}
public static void processMenu(String menu) {
String[] items = menu.split("\n");
// 用于存储总价
double totalPrice = 0.0;
System.out.println("菜单中的价格数据:");
for (String item : items) {
String priceStr = item.replaceAll("[^0-9.]", "");
// 将价格字符串转换为double类型
double price = Double.parseDouble(priceStr);
System.out.printf("%.2f\n", price);
// 累加总价
totalPrice += price;
}
// 输出总价
System.out.println("\n菜品总价格:" + String.format("%.2f", totalPrice) + "元");
}
}
3. 分割字符串
public class StringSplitter {
public static void main(String[] args) {
String text = "苹果,香蕉;橙子|葡萄";
String regex = "[,;|]";
String[] fruits = text.split(regex);
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
4. 实用示例
public class RegexExamples {
public static void main(String[] args) {
// 提取价格的多种方法
String price = "价格:¥99.99元";
// 方法1:提取数字和小数点
String price1 = price.replaceAll("[^0-9.]", "");
System.out.println(price1); // "99.99"
// 方法2:使用正则表达式捕获组
String price2 = price.replaceAll(".*¥(\\d+\\.\\d+)元.*", "$1");
System.out.println(price2); // "99.99"
// 方法3:使用Pattern和Matcher类
Pattern pattern = Pattern.compile("\\d+\\.\\d+");
Matcher matcher = pattern.matcher(price);
if (matcher.find()) {
System.out.println(matcher.group()); // "99.99"
}
}
}
public class ReplaceAll {
public static void main(String[] args) {
System.out.println("""
如果不需要正则表达式功能,优先使用replace,因为它会更高效。\s
使用replaceAll时需要注意转义字符,因为正则表达式对某些字符(如.、*、?等)有特殊含义。
如果不需要正则表达式功能,优先使用replace,因为它会更高效。\s
使用replaceAll时需要注意转义字符,因为正则表达式对某些字符(如.、*、?等)有特殊含义。""");
// String replace(CharSequence target, CharSequence replacement);
String text1 = "hello world";
String replacedText1 = text1.replace("o", "a"); // 替换所有的 "o" 为 "a"
System.out.println(replacedText1); // 输出 "hella warld"
//String replaceAll(String regex, String replacement);
String text2 = "hello world";
String replacedText2 = text2.replaceAll("o", "a"); // 替换所有的 "o" 为 "a"
System.out.println(replacedText2); // 输出 "hella warld"
// 使用正则表达式替换所有的非字母字符
String textWithSymbols = "hello123 world!";
String replacedTextWithSymbols = textWithSymbols.replaceAll("[^a-zA-Z]", " ");
System.out.println(replacedTextWithSymbols); // 输出 "hello world "
}
}
五、常用方法
Pattern类方法
compile(String regex)
:编译正则表达式。compile(String regex, int flags)
:指定匹配标志编译正则表达式,如忽略大小写等。
Matcher类方法
matches()
:尝试将整个区域与模式匹配。find()
:扫描输入序列以查找下一个匹配。group()
:返回以前匹配操作的匹配结果。start()
和end()
:返回匹配的起始和结束索引。replaceAll(String replacement)
:替换所有匹配的子字符串。
六、注意事项与结论
-
转义字符:由于反斜杠在Java字符串中是转义字符,所以正则表达式中的反斜杠需要写成双反斜杠。例如,特殊字符(如
.
,*
,+
,?
,|
,(
,)
,[
,]
,{
,}
,^
,$
)需要用\
转义,\d
在Java中需要写成"\\d"
。 -
性能优化:对于频繁使用的正则表达式,应该将其编译为
Pattern
对象并重复使用,而不是每次都编译,避免使用过于复杂的正则表达式,尽量使用具体的字符类而不是通配符。 -
输入验证:使用正则表达式进行输入验证时,要考虑全面,避免正则表达式过于宽松或严格。
掌握Java中的正则表达式可以大大提高字符串处理的效率和能力。通过Pattern
和Matcher
类,可以灵活地编译和应用正则表达式,实现复杂的文本匹配和操作。