正则表达式是一种用于描述字符串模式的工具,它在文本处理、数据验证、搜索和替换等方面有着广泛的应用。这篇文章,我们将分析什么是正则表达式以及它是如何工作的?
什么是正则表达式?
正则表达式(regular expression,常简写为 regex、regexp 或 RE),又称规律表达式、正规表示式、正规表示法、规则运算式、常规表示法,是计算机科学概念,用简单字串来描述、匹配文中全部符合指定格式的字串,現在很多文本编辑器都支援用正则表达式搜寻、取代符合指定格式的字串。
Java Regex是一种用于匹配字符串的模式,它可以用来验证、查找、替换或拆分字符串。Java中的正则表达式由 java.util.regex包提供,主要由 3 个类和 1 个接口组成:
- Pattern Class:表示正则表达式的编译表示。
- Matcher Class:用于执行匹配操作的引擎。
- PatternSyntaxException Class:表示正则表达式语法错误的异常。
- MatchResult Interface:用于表示匹配操作的结果。
正则表达式组成
Java 正则表达式主要由以下几部分组成:
- 字符类:用于匹配指定范围内的任意字符。例如[a-z]表示匹配任意小写字母。
- 预定义字符类:简化的字符类。例如\d表示匹配任意数字,\w表示匹配任意字母、数字或下划线。
- 量词:用于指定字符或子表达式的重复次数。例如a*表示匹配零次或多次 a,a{2,4}表示匹配 2 到 4 次 a。
- 边界匹配符:用于匹配字符串的边界。例如^表示匹配字符串的开始,$表示匹配字符串的结束。
- 分组:用于将多个字符或子表达式组合在一起。例如(abc)表示匹配字符串 "abc"。
下面还列举了一些常见的正则表达式元素:
- .: 匹配除换行符以外的任意单字符
- *: 匹配前面的子表达式零次或多次
- +: 匹配前面的子表达式一次或多次
- ?: 匹配前面的子表达式零次或一次
- \d: 匹配一个数字字符,[0-9] 的缩写
- \D 匹配任何非数字,[^0-9] 的缩写
- \s 任何空格字符,[\t\n\x0B\f\r] 的缩写
- \S 任何非空格字符,是 [^\s] 的缩写
- \w: 匹配一个字母、数字或下划线字符
- [abc]: 匹配方括号内的任意一个字符
- ^: 匹配字符串的开始
- $: 匹配字符串的结束
更多表达式,参考: regexr
Regex 类详解
1.Matcher
Matcher类实现 MatchResult 接口,它是一个正则表达式引擎,用于对字符序列执行匹配操作。主要包含以下方法:
- boolean matches():测试正则表达式是否与模式匹配。
- boolean find():找到与模式匹配的下一个表达式。
- boolean find(int start):找到与给定起始编号中的模式匹配的下一个表达式。
- String group():返回匹配的子序列。
- int start():返回匹配子序列的起始索引。
- int end():返回匹配子序列的结束索引。
- int groupCount():返回匹配子序列的总数。
2.Pattern
Pattern类是正则表达式的编译版本,用于定义正则表达式引擎的模式。主要包含以下方法:
- static Pattern compile(String regex):编译给定的正则表达式并返回 Pattern 的实例。
- Matcher matcher(CharSequence input):创建一个匹配器,该匹配器将给定的输入与模式匹配。
- static boolean matches(String regex, CharSequence input):它作为编译和匹配器方法的组合工作。它编译正则表达式并将给定的输入与模式匹配。
- String[] split(CharSequence input):围绕给定模式的匹配项拆分给定的输入字符串。
- String pattern():返回正则表达式模式。
3.PatternSyntaxException
PatternSyntaxException 类是抛出未经检查的异常,指示正则表达式模式中的语法错误。主要包含以下方法:
- int getIndex():检索异常的索引
- String getDescription():检索异常的描述信息
- String getPattern():检索错误的正则表达式模式
4.MatchResult
MatchResult接口主要用于匹配操作的结果。此接口包含用于确定与正则表达式匹配的结果的查询方法。匹配边界、组和组边界可以通过。主要包含以下方法:
- int start():返回匹配的开始索引
- int start(int group):返回本次匹配期间给定组捕获的子序列的起始索引。
- int end():返回最后一个匹配字符后的偏移量。
- int end(int group):返回本次匹配期间给定组捕获的子序列的最后一个字符后的偏移量。
- String group():返回与上一个匹配项匹配的输入子序列。
- String group(int group):返回上一次匹配操作期间给定组捕获的输入子序列。
- int groupCount():返回此匹配结果模式中的捕获组的数量。
正则使用场景
正则使用场景主要包含以下类型:
- 输入验证,比如邮箱验证,手机号验证,URL 验证,密码强度验证
- 文本搜索和替换,比如查找特定模式,替换特定模式
- 文本拆分,比如按照空白字符拆分字符串
- 日志和数据解析,比如提取IP地址,提取日期和时间
- 数据清洗,比如删除HTML标签,格式化字符串
- 编译器和解释器,比如识别标识符、关键字、操作符等
- 数据库查询,比如使用 SQL 的 REGEXP 运算符进行复杂的模式匹配查询。
- 文件名匹配,比如查找所有以 .txt 结尾的文件
除了上面的场景,正则表达式还可以使用到其他的场景,需要根据具体的场景而定。
示例演示
1.邮箱验证
验证邮箱地址是一个常见的正则表达式应用场景。首先,我们需要一个能够验证邮箱地址的正则表达式。一个常见的用于验证邮箱的正则表达式如下:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
该正则表达式的解释如下:
- ^:匹配字符串的开始。
- [a-zA-Z0-9._%+-]+:匹配一个或多个字母、数字、点、下划线、百分号、加号或减号。
- @:匹配@符号。
- [a-zA-Z0-9.-]+:匹配一个或多个字母、数字、点或减号。
- \.:匹配一个点。
- [a-zA-Z]{2,}:匹配两个或更多的字母。
- $:匹配字符串的结束。
下面是一个完整的 Java示例代码:
import java.util.regex.*;
public class EmailValidator {
public static void main(String[] args) {
String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
String[] emails = {
"valid.email@example.com",
"invalid-email@example",
"another.valid.email@example.co.uk",
"invalid.email@.com",
"valid_email123@example.org"
};
Pattern pattern = Pattern.compile(emailPattern);
for (String email : emails) {
Matcher matcher = pattern.matcher(email);
boolean isMatch = matcher.matches();
System.out.println("Email: " + email + " is valid? " + isMatch);
}
}
}
运行结果:
Email: valid.email@example.com is valid? true
Email: invalid-email@example is valid? false
Email: another.valid.email@example.co.uk is valid? true
Email: invalid.email@.com is valid? false
Email: valid_email123@example.org is valid? true
在上述代码中:
- Pattern.compile(emailPattern):编译正则表达式。
- pattern.matcher(email):创建一个匹配器对象,用于匹配给定的邮箱字符串。
- matcher.matches():检查整个字符串是否与正则表达式匹配。
2.拆分字符串
在下面的示例中,正则表达式\s+表示一个或多个空白字符。split方法用于将字符串按匹配的模式拆分为多个部分。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String pattern = "\\s+";
String text = "Split this string by spaces.";
Pattern compiledPattern = Pattern.compile(pattern);
String[] parts = compiledPattern.split(text);
for (String part : parts) {
System.out.println(part);
}
}
}
3.查找子字符串
在下面示例中,正则表达式\d+表示一个或多个数字字符。find方法用于查找所有匹配的子字符串。
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String pattern = "\\d+";
String text = "There are 123 apples and 456 oranges.";
Pattern compiledPattern = Pattern.compile(pattern);
Matcher matcher = compiledPattern.matcher(text);
while (matcher.find()) {
System.out.println("Found a number: " + matcher.group());
}
}
}
总结
正则表达式是一种功能强大且灵活的工具,能够极大地提高字符串处理的效率和精度。正则表达式的技术难度不大,但是很难记忆,而且在输入验证、文本搜索和替换、文本拆分、日志和数据解析、数据清洗、编译器和解释器等应用场景使用比较多。所以,掌握正则表达式还是有很大帮助。