正则表达式是一种用于描述字符串模式的工具,它在文本处理、数据验证、搜索和替换等方面有着广泛的应用。这篇文章,我们将分析什么是正则表达式以及它是如何工作的?
什么是正则表达式?
正则表达式(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 类详解
Matcher
Matcher
类实现 MatchResult
接口,它是一个正则表达式引擎,用于对字符序列执行匹配操作。主要包含以下方法:
- boolean matches():测试正则表达式是否与模式匹配。
- boolean find():找到与模式匹配的下一个表达式。
- boolean find(int start):找到与给定起始编号中的模式匹配的下一个表达式。
- String group():返回匹配的子序列。
- int start():返回匹配子序列的起始索引。
- int end():返回匹配子序列的结束索引。
- int groupCount():返回匹配子序列的总数。
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():返回正则表达式模式。
PatternSyntaxException
PatternSyntaxException
类是抛出未经检查的异常,指示正则表达式模式中的语法错误。主要包含以下方法:
- int getIndex():检索异常的索引
- String getDescription():检索异常的描述信息
- String getPattern():检索错误的正则表达式模式
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 结尾的文件
除了上面的场景,正则表达式还可以使用到其他的场景,需要根据具体的场景而定。
示例演示
邮箱验证
验证邮箱地址是一个常见的正则表达式应用场景。首先,我们需要一个能够验证邮箱地址的正则表达式。一个常见的用于验证邮箱的正则表达式如下:
^[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():检查整个字符串是否与正则表达式匹配。
拆分字符串
在下面的示例中,正则表达式\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); } } }
查找子字符串
在下面示例中,正则表达式\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()); } } }
总结
正则表达式是一种功能强大且灵活的工具,能够极大地提高字符串处理的效率和精度。正则表达式的技术难度不大,但是很难记忆,而且在输入验证、文本搜索和替换、文本拆分、日志和数据解析、数据清洗、编译器和解释器等应用场景使用比较多。所以,掌握正则表达式还是有很大帮助。