Jakob Jenkov 2019-03-05
Java 正则表达式(Java Regex)是 Java 官方提供的正则表达式 API。"Java Regex" 是 "Java Regular Expression" 的缩写。该 API 位于 java.util.regex 包中,自 Java 1.4 起就已成为标准 Java(JSE)的一部分。
本教程涵盖的是 Java 8 中包含的 Java Regex API。
正则表达式简介
正则表达式是一种用于在文本中搜索的文本模式。你可以通过将正则表达式与目标文本进行“匹配”来实现搜索。
匹配的结果可能是:
- 一个布尔值(
true/false),表示是否匹配成功; - 一组匹配项——即正则表达式在文本中每次出现的位置。
例如,你可以使用正则表达式在一个 Java 字符串 中查找电子邮件地址、URL、电话号码、日期等。这通过将不同的正则表达式与字符串进行匹配来完成,每个正则表达式会返回其所有匹配项。
接下来的部分将展示如何使用 Java Regex API 进行匹配操作。但在那之前,我们先介绍 Java Regex API 的两个核心类。
Java Regex 核心类
Java Regex API 包含两个核心类:
Pattern类:用于创建模式(即正则表达式)。它表示一个预编译的正则表达式对象,可用于对文本进行匹配。Matcher类:用于将给定的Pattern对象多次与一段文本进行匹配,从而找出该正则表达式在文本中的所有出现位置。你可以从Pattern实例获取Matcher实例。
这两个类在各自的文档中有详细说明(见上方或页面左上角链接)。
Java 正则表达式示例
如前所述,Java Regex API 可以:
- 判断某个正则表达式是否匹配某段字符串;
- 返回该正则表达式在字符串中的所有匹配项。
下面分别给出这两种用法的示例。
Pattern 示例
以下是一个简单的 Java 正则表达式示例,用于检查文本中是否包含子字符串 http://:
String text = "This is the text to be searched " +
"for occurrences of the http:// pattern.";
String regex = ".*http://.*";
boolean matches = Pattern.matches(regex, text);
System.out.println("matches = " + matches);
text变量包含要检查的文本。regex变量包含正则表达式:.*http://.*,表示任意字符(0个或多个)+http://+ 任意字符(0个或多个)。Pattern.matches()是一个静态方法,用于判断整个字符串是否匹配该正则表达式。
注意:此正则表达式不会验证 URL 是否合法(如是否包含域名和后缀
.com等),它只检查是否存在http://子串。
Matcher 示例
以下示例使用 Matcher 类在文本中查找子字符串 "is" 的所有出现位置:
String text = "This is the text which is to be searched " +
"for occurrences of the word 'is'.";
String regex = "is";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
int count = 0;
while(matcher.find()) {
count++;
System.out.println("found: " + count + " : " +
matcher.start() + " - " + matcher.end());
}
- 通过
Pattern获取Matcher; - 使用
matcher.find()循环查找所有匹配; matcher.start()和matcher.end()返回匹配的起止索引。
Java 正则表达式语法
不同编程语言的正则表达式语法略有差异。Java 使用自己的正则语法,下面介绍常用规则。
匹配字符
最简单的正则表达式就是直接匹配字面字符:
String regex = "http://";
该表达式仅匹配完全等于 "http://" 的字符串。如果前后有其他字符(如 "The URL is: http://mydomain.com"),则不匹配。
元字符(Metacharacters)
以下字符在正则表达式中有特殊含义,称为元字符:
< > ( ) [ ] { } \ ^ - = $ ! | ? * + .
例如,. 不代表句点,而是“任意字符”(见下文)。
转义字符
若要匹配元字符的字面值(如真正的句点 .),需使用反斜杠 \ 转义:
String regex = "\\.";
注意:在 Java 字符串中,
\本身是转义字符,因此要表示一个\,需写成\\。
所以\\.在正则引擎中实际是\.,表示匹配字面句点。
同理,匹配反斜杠本身需写成:
String regex = "\\\\";
匹配任意字符
使用 .(英文句点)可匹配任意单个字符(除换行符外):
String regex = ".";
// 匹配任意一个字符
String regex = "H.llo";
// 匹配 "Hello", "Hallo", "Hxllo" 等
匹配一组字符中的任意一个(字符类)
使用方括号 [...] 定义字符集合:
String regex = "H[ae]llo";
// 匹配 "Hallo" 或 "Hello"
[a-z]:匹配任意小写字母;[a-zA-Z]:匹配任意字母(大小写);[0-9]:匹配任意数字。
若要在字符类中匹配字面 [ 或 ],需转义:
String regex = "H[\\[\\]]llo";
// 匹配 "H[llo" 或 "H]llo"
匹配字符范围
如上所述,[a-z] 表示从 a 到 z 的所有小写字母。
匹配数字
使用预定义字符类 \d(等价于 [0-9]):
String regex = "Hi\\d";
// 匹配 "Hi0", "Hi5" 等,但不匹配 "Hip"
匹配非数字
使用 \D(大写 D):
String regex = "Hi\\D";
// 匹配 "Hi+", "Hi@" 等,但不匹配 "Hi3"
匹配单词字符
\w 等价于 [a-zA-Z_0-9]:
String regex = "Hi\\w";
// 匹配 "HiA", "Hi_", "Hi5" 等
匹配非单词字符
使用 \W(大写 W):
String regex = "Hi\\W";
// 匹配 "Hi!", "Hi "(空格)等
边界匹配
Java Regex 支持多种边界匹配:
| 符号 | 含义 |
|---|---|
^ |
行或字符串开头 |
$ |
行或字符串结尾 |
\b |
单词边界 |
\B |
非单词边界 |
\A |
输入开头 |
\G |
上次匹配结束处 |
\Z |
输入结尾(忽略最后的终止符) |
\z |
输入绝对结尾 |
行(或字符串)开头
^ 通常用于检查字符串是否以某内容开头:
String text = "http://jenkov.com";
Pattern pattern = Pattern.compile("^http://");
注意:尽管文档称
^匹配“行首”,但在实际测试中,它通常只匹配整个输入字符串的开头(除非启用多行模式)。
行(或字符串)结尾
$ 用于检查字符串是否以某内容结尾:
String text = "http://jenkov.com";
Pattern pattern = Pattern.compile(".com$");
单词边界(\b)
\b 匹配单词的开始或结束位置(如空格、标点前后):
String text = "Mary had a little lamb";
Pattern pattern = Pattern.compile("\\bl");
// 查找以 "l" 开头的单词(如 "little", "lamb")
输出匹配位置(索引):
Found match at: 12 to 13 // "little" 的 l
Found match at: 19 to 20 // "lamb" 的 l
非单词边界(\B)
\B 匹配单词内部的边界(即两个都是单词字符之间的位置):
String text = "Mary";
Pattern pattern = Pattern.compile("\\B");
// 匹配索引 1, 2, 3(M-a, a-r, r-y 之间)
量词(Quantifiers)
量词用于指定匹配次数:
*:0 次或多次+:1 次或多次{n}:恰好 n 次{n,m}:n 到 m 次
示例:
String regex = "Hello*"; // 匹配 "Hell", "Hello", "Helloo"...
String regex = "Hello+"; // 必须至少一个 o
String regex = "Hello{2}"; // 必须两个 o → "Helloo"
String regex = "Hello{2,4}"; // 2~4 个 o
若要匹配字面 * 或 +,需转义:
String regex = "Hell\\+"; // 匹配 "Hell+"
逻辑运算符
与(AND)
默认情况下,正则表达式中的连续模式表示“与”:
Pattern.compile("[Cc][Ii].*");
// 必须先匹配 [Cc],再匹配 [Ii],再匹配任意字符
或(OR)
使用 | 表示“或”:
Pattern.compile(".*Ariel.*|.*Sleeping Beauty.*");
// 匹配包含 "Ariel" 或 "Sleeping Beauty" 的字符串
Java String 类中的正则方法
matches()
判断整个字符串是否匹配正则表达式:
String text = "one two three two one";
boolean matches = text.matches(".*two.*"); // true
split()
按正则表达式分割字符串:
String[] parts = text.split("two");
// 结果: ["one ", " three ", " one"]
replaceFirst()
替换第一个匹配项:
String s = text.replaceFirst("two", "five");
// "one five three two one"
replaceAll()
替换所有匹配项:
String t = text.replaceAll("two", "five");
// "one five three five one"