文档库 最新最全的文档下载
当前位置:文档库 › Java正则表达式详解(非常适合入门)

Java正则表达式详解(非常适合入门)

本文由hmsole贡献
doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。
Java 正则表达式教程
Regular Expressions of Java Tutorial 译者序
[1]
正则表达式善于处理文本,对匹配,搜索和替换等操作都有意想不到的作用.正 因 如 此 , 正 则 表 达 式 现 在 是 作 为 程 序 员 七 种 基 本 技 能 之 一 *, 因 此 学 习 和 使 用 它 在 工 作 中都能达到很高的效率. 正 则 表 达 式 应 用 于 程 序 设 计 语 言 中 , 首 次 是 出 现 在 Perl 语 言 , 这 也 让 Perl 奠 定了正则表达式旗手的地位.现在,它已经深入到了所有的程序设计语言中,在程序 设计语言中,正则表达式可以说是标准配置了. Java 中 从 JDK 1.4 开 始 增 加 了 对 正 则 表 达 式 的 支 持 , 至 此 正 则 表 达 式 成 为 了 Java 中 的 基 本 类 库 , 使 用 时 不 需 要 再 导 入 第 三 方 的 类 库 了 . Java 正 则 表 达 式 的 语 法 来 源 于 象 征 着 正 则 表 达 式 标 准 的 Perl 语 言 , 但 也 不 是 完 全 相 同 的 , 具 体 的 可 以 参 看 Pattern 类 的 API 文 档 说 明 . 我 在 一 次 偶 然 中 发 现 了 位 于 https://www.wendangku.net/doc/7617477729.html, 站 点 上 的 Java Tutorial, 也 在 那 里 看 到 了 关 于 Java 的 正 则 表 达 式 教 程 , 感 觉 它 不 同 于 其 他 的 正 则 表 达 式 教 程 , 文 中 以 大 量 的 匹 配 实 例 来 进 行 说 明 . 为 了 能 让 Java 学 习 者 能 更 好 地 使 用 正 则 表 达 式 , 就 将 其 完 整 地 译出了.该教程中所介绍的正则表达式应用仅仅是最为简单的(并没有完全地涉及到 Pattern 类 支 持 的 所 有 正 则 表 达 式 语 法 , 也 没 有 涉 及 到 高 级 的 应 用 ), 适 合 于 从 未 接 触 过或者是尚未完全明白正则表达式基础的学习者.在学习完该教程后,应该对正则表 达 式 有 了 初 步 的 了 解 , 并 能 熟 练 地 运 用 java.util.regex 包 中 的 关 于 正 则 表 达 式 的 类 库,为今后学习更高级的正则表达式技术奠定良好的基础. 教 程 中 所 有 的 源 代 码 都 在 src 目 录 下 , 可 以 直 接 编 译 运 行 . 由 于 当 前 版 本 的 Java
Tutorial 是 基 于 JDK 6.0 的 , 因 此 其 中 的 示 例 程 序 也 用 到 了 JDK 6.0 中 的 新 增 类 库 , 但
正 则 表 达 式 在 JDK 1.4 就 已 经 存 在 了 , 为 了 方 便 大 家 使 用 , 改 写 了 部 分 的 源 代 码 , 源 代 码 类 名 中 后 缀 为 " V4" 的 表 示 用 于 JDK 1.4 或 以 上 版 本 , " V5" 的 表 示 用 于 JDK 5.0 或 以 上 版 本 , 没 有 这 些 后 缀 的 类 在 各 个 版 本 中 均 可 以 正 常 使 用 . 由于译者的水平和技术能力有限,译稿虽经多次校对,难免有疏漏之处,敬请大
家 批 评 和 指 正 . 若 有 发 现 不 妥 之 处 , 请 发 送 邮 件

至 FrankieGao123@https://www.wendangku.net/doc/7617477729.html,, 我 会 在 blog 中进行勘误,谢谢! 火龙果顿首! 2008 年 2 月 27 日
这是由《程序员》杂志社评出的,刊登在《程序员》2007 年 3 月刊上.这七种基本技能是:数组,字符串 与哈希表,正则表达式,调试,两门语言,一个开发环境,SQL 语言和编写软件的思想.
目录
译者序 序 0 引言
o o
0.1 什么是正则表达式? 0.2 java.util.regex 包是如何描述正则表达式的?
1 2
测试用具 字符串
o
2.1 元字符
3
字符类
o
3.1 简单类 3.1.1 否定 3.1.2 范围 3.1.3 并集 3.1.4 交集 3.1.5 差集
4 5
预定义字符类 量词
o o o
5.1 零长度匹配 5.2 捕获组和字符类中的量词 5.3 贪婪,勉强和侵占量词间的不同
6
捕获组
o o
6.1 编号方式 6.2 反向引用
7 8
边界匹配器 Pattern 类的方法
o o o o o o
8.1 使用标志构建模式 8.2 内嵌标志表达式 8.3 使用 matches(String, CharSequence) 方法 8.4 使用 split(String) 方法 8.5 其他有用的方法 8.6 在 https://www.wendangku.net/doc/7617477729.html,ng.String 中等价的 Pattern 方法
9
Matcher 类的方法
o o o o o
9.1 使用 start 和 end 方法 9.2 使用 matches 和 lookingAt 方法 9.3 使用 replaceFirst(String) 和 replaceAll(String) 方法 9.4 使用 appendReplacement(StringBuffer, String) 和 appendTail(StringBuffer) 方法 9.5 在 https://www.wendangku.net/doc/7617477729.html,ng.String 中等价的 Matcher 方法
10 11 12 注释
PatternSyntaxException 类的方法 更多的资源 问题和练习
译后记
序 返回目录
本 文 介 绍 如 何 使 用 java.util.regex API 作 为 正 则 表 达 式 模 式 匹 配 . 虽 然 说 这 个 包 中 可 被 接 受 的 语 法 参 数 与 Perl 是 相 似 的 , 但 我 们 并 不 需 要 掌 握 Perl 的 语 法 知 识.本教程将从基础开始,逐层深入到更多的高级技巧.下面是各章节的主要内容:
0
引言
粗 略 地 看 一 下 正 则 表 达 式 , 同 时 也 介 绍 组 成 API 的 核 心 类 .
1
测试用具
编写了一个简单的应用程序,用于测试正则表达式的模式匹配.
2
字符串
介绍基本的模式匹配,元字符和引用.
3
字符类
描述简单字符类,否定,范围,并集,交集和差集.
4
预 定 义 字 符类
描述空白字符,字母和数字字符等基本的预定义字符.
5
量词
使 用 贪 婪 ( greedy) , 勉 强 ( reluctant) 和 侵 占 ( possessive) 量 词 , 来 匹 配 指
定表达式 X 的次数.
6
捕获组
解释如何把多个字符作为一个单独的单元进行处理.
7
边界匹配器
描述行,单词和输入的边界.
8
Pattern 类 的方 法
测 试 了 Pattern 中 一 些 有 用 的 方 法 , 以 及 探 究 一 些 高 级 的 特 性 , 诸 如 : 带 标 记 的
编译和使

用内嵌标记表达式.
9
Matcher 类 的 方 法
描 述 了 Matcher 类 中 通 常 使 用 的 方 法 .
10
PatternSyntaxException 类 的 方 法
描 述 了 如 何 检 查 一 个 PatternSyntaxException 异 常 .
11
更多的资源
要了解更多正则表达式,可以参考这一节.
12
问题和练习
巩固一下本教程所介绍的正则表达式的基本知识,并附有答案.
为 了 区 分 文 档 中 的 正 则 表 达 式 和 普 通 字 符 串 , 均 以 \d[abc]{2}的 形 式 表 示 正 则 表 达式的模式.
0
0.1
引言 返回目录
什么是正则表达式? 什么是正则表达式?返回目录
正 则 表 达 式 ( regular expressions) 是 一 种 描 述 字 符 串 集 的 方 法 , 它 是 以 字 符 串
集中各字符串的共有特征为依据的.正则表达式可以用于搜索,编辑或者是操作文本 和 数 据 . 它 超 出 了 Java 程 序 设 计 语 言 的 标 准 语 法 , 因 此 有 必 要 去 学 习 特 定 的 语 法 来 构建正则表达式.正则表达式的变化是复杂的,一旦你理解了它们是如何被构造的 话,你就能解析或者构建任意的正则表达式了. 本 教 程 讲 授 java.util.regex API 所 支 持 的 正 则 表 达 式 语 法 , 以 及 介 绍 几 个 可 运 行的例子来说明不同的对象间是如何交互的.在正则表达式的世界中,有不同风格的 选 择 , 比 如 : grep [2], Perl, Tcl, Python, PHP 和 awk. java.util.regex API 中 的 正 则 表 达 式 语 法 与 Perl 中 的 最 为 相 似 .
0.2
java.util.regex 包是如何描述正则表达式的?返回目录 包是如何描述正则表达式的?
java.util.regex 包 主 要 由 三 个 类 所 组 成 : Pattern, Matcher 和
PatternSyntaxException.
Pattern 对 象 表 示 一 个 已 编 译 的 正 则 表 达 式 . Pattern 类 没 有 提 供 公 共 的 构 造 方 法 . 要 构 建 一 个 模 式 , 首 先 必 须 调 用 公 共 的 静 态 compile 方 法 , 它 将 返 回 一 个 Pattern 对 象 . 这 个 方 法 接 受 正 则 表 达 式 作 为 第 一 个 参 数 . 本 教 程 的开始部分将教你必需的语法.
Matcher 是 一 个 靠 着 输 入 的 字 符 串 来 解 析 这 个 模 式 和 完 成 匹 配 操 作 的 对 象 . 与 Pattern 相 似 , Matcher 也 没 有 定 义 公 共 的 构 造 方 法 , 需 要 通 过 调 用 Pattern 对 象 的 matcher 方 法 来 获 得 一 个 Matcher 对 象 .
PatternSyntaxException 对 象 是 一 个 未 检 查 异 常 , 指 示 了 正 则 表 达 式 中 的 一个语法错误. 本教程的最后几节课程会详细地说明各个类.首当其冲的问题是:必须理解正则
表达式是如何被构建的,因此下一节引入了一个简单的测试用具,重复地用于探究它 们的语法.
1
测试用具 返回目录
这 节 给 出 了 一 个 可 重

用 的 测 试 用 具 RegexTestHarness.java, 用 于 探 究 构 建 API 所 支
持的正则表达式.使用
java RegexTestHarness 这 个 命 令 来 运 行 , 没 有 被 接 受 的 命 令 行 参 数 . 这 个 应 用 会 不 停 地 循 环 执 行 下 去 [3], 提 示用户输入正则表达式和字符串.虽然说使用这个测试用具是可选的,但你会发现它 用于探究下文所讨论的测试用例将更为方便.
import java.io.Console; import java.util.regex.Pattern; import java.util.regex.Matcher; public class RegexTestHarness { public static void main(String[] args) { Console console = System.console(); if (console == null) { System.err.println("No console."); System.exit(1); } while (true) { Pattern pattern = https://www.wendangku.net/doc/7617477729.html,pile(console.readLine("%nEnter your regex: ")); Matcher matcher = pattern.matcher(console.readLine("Enter input string to search: ")); boolean found = false; while (matcher.find()) { console.format("I found the text \"%s\" starting at index %d " + "and ending at index %d.%n", matcher.group(), matcher.start(), matcher.end()); found = true; } if (!found) { console.format("No match found.%n"); }
} } }
在继续下一节之前,确认开发环境支持必需的包,并保存和编译这段代码.
【译者注】
由 于 当 前 版 本 的 Java Tutorial 是 基 于 JDK 6.0 编 写 的 , 上 述 的 测 试 用 具 由 于 使 用 到 JDK 6.0 中 新 增 的 类 库 ( java.io.Console) , 所 以 该 用 具 只 能 在 JDK 6.0 的 环 境 中 编 译 运 行 , 由 于 Console 访 问 操 作 系 统 平 台 上 的 控 制 台 , 因 此 这 个 测 试 用 具 只 能 在 操 作 系 统 的 字 符 控 制 台 中 运 行 , 不 能 运 行 在 IDE 的 控 制 台 中 . 正 则 表 达 式 是 JDK 1.4 所 增 加 的 类 库 , 为 了 兼 容 JDK 1.4 和 JDK 5.0 的 版 本 , 重新改写了这个测试用具,让其能适用于不同的版本. JDK 5.0 适 用 的 测 试 用 具 ( RegexTestHarnessV5.java, 该 用 具 可 以 在 IDE 中 执 行 ) , 建 议 JDK 6.0 环 境 也 采 用 该 用 具 .
import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTestHarnessV5 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (true) { System.out.printf("%nEnter your regex: "); Pattern pattern = https://www.wendangku.net/doc/7617477729.html,pile(scanner.nextLine()); System.out.printf("Enter input string to search: "); Matcher matcher = pattern.matcher(scanner.nextLine()); boolean found = false; while (matcher.find()) { System.out.printf( "I found the text \"%s\" starting at index %d and ending at index %d.%n", matcher.group(), matcher.start(), matcher.end() ); found = true; } if (!found) { System.out.printf("No match found.%n"); }
} } }
JDK 1.4 适 用 的 测 试 用 具 ( RegexTestHarnessV4.java) :
import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.Inpu

tStreamReader; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTestHarnessV4 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader( new InputStreamReader(new BufferedInputStream(System.in)) ); while (true) { System.out.print("\nEnter your regex: "); Pattern pattern = https://www.wendangku.net/doc/7617477729.html,pile(br.readLine()); System.out.print("Enter input string to search: "); Matcher matcher = pattern.matcher(br.readLine()); boolean found = false; while (matcher.find()) { System.out.println("I found the text \"" + matcher.group() + "\" starting at index " + matcher.start() + " and ending at index " + matcher.end() + "."); found = true; } if (!found) { System.out.println("No match found."); } } } }
2
字符串 返回目录
在 大 多 数 的 情 况 下 , API 所 支 持 模 式 匹 配 的 基 本 形 式 是 匹 配 字 符 串 , 如 果 正 则 表 达
式 是 foo, 输 入 的 字 符 串 也 是 foo, 这 个 匹 配 将 会 是 成 功 的 , 因 为 这 两 个 字 符 串 是 相 同 的.试着用测试用具来测试一下:
Enter your regex: foo Enter input string to search: foo I found the text "foo" starting at index 0 and ending at index 3. 结果确实是成功的.注意当输入的字符串是 3 个字符长度的时候,开始的索引是 0, 结 束 的 索 引 是 3. 这 个 是 约 定 俗 成 的 , 范 围 包 括 开 始 的 索 引 , 不 包 括 结 束 的 索 引 , 如下图所示:
图 1
字 符 串 " foo" 的 单 元 格 编 号 和 索 引 值 [4]
字 符 串 中 的 每 一 个 字 符 位 于 其 自 身 的 单 元 格 ( cell) 中 , 在 每 个 单 元 格 之 间 有 索 引 指 示 位 . 字 符 串 " foo" 始 于 索 引 0 处 , 止 于 索 引 3 处 , 即 使 是 这 些 字 符 它 们 自 己 仅 占 据 了 0, 1 和 2 号 单 元 格 . 就子序列匹配而言,你会注意到一些重叠,下一次匹配开始索引与前一次匹配的 结束索引是相同的:
Enter your regex: foo Enter input string to I found the text "foo" I found the text "foo" I found the text "foo"
search: foofoofoo starting at index 0 and ending at index 3. starting at index 3 and ending at index 6. starting at index 6 and ending at index 9.
2.1
元字符返回目录
API 也 支 持 许 多 可 以 影 响 模 式 匹 配 的 特 殊 字 符 . 把 正 则 表 达 式 改 为 cat.并 输 入 字
符 串 " cats" , 输 出 如 下 所 示 : Enter your regex: cat.
Enter input string to search: cats I found the text "cats" starting at index 0 and ending at index 4. 虽 然 在 输 入 的 字 符 串 中 没 有 点 ( .) , 但 这 个 匹 配 仍 然 是 成 功 的 . 这 是 由 于 点 ( .) 是 一 个 元 字 符 ( metacharacters) 被 这 个 匹 配 翻 译 成 了 具 有 特 殊 意 义 的 字 符 了 ) . 这 ( 个 例 子 为 什 么 能 匹 配 成 功 的 原 因 在 于 , 元 字 符 .指 的 是 " 任 意 字

符 " . API 所 支 持 的 元 字 符 有 : ([{\^-$|}])?*+.
注意:在学习过更多的如何构建正则表达式后,你会碰到这些情况:上面的这些特殊 字符不应该被处理为元字符.然而也能够使用这个清单来检查一个特殊的字符 是 否 会 被 认 为 是 元 字 符 . 例 如 , 字 符 !, @ 和 # 决 不 会 有 特 殊 的 意 义 . 有两种方法可以强制将元字符处理成为普通字符: 1. 在 元 字 符 前 加 上 反 斜 线 ( \) ; 2. 把 它 放 在 \Q( 引 用 开 始 ) 和 \E( 引 用 结 束 ) 之 间 [5]. 在 使 用 这 种 技 术 时 , \Q 和 \E 能 被 放 于 表 达 式 中 的 任 何 位 置 ( 假 设 先 出 现 \Q [6])
3
字符类 返回目录
如 果 你 曾 看 过 Pattern 类 的 说 明 , 会 看 到 一 些 构 建 正 则 表 达 式 的 概 述 . 在 这 一 节 中
你会发现下面的一些表达式:
字符 类
[abc]
a, b 或 c( 简 单 类 ) 除 a, b 或 c 之 外 的 任 意 字 符 取 (
[^abc]
反) a 到 z, 或 A 到 Z, 包 括( 范 围 ) a 到 d, 或 m 到 p: [a-dm-p]
[a-zA-Z]
[a-d[m-p]]
(并集) d, e 或 f( 交 集 )
[a-z&&[def]]
除 b 和 c 之外的 a 到 z 字 [a-z&&[^bc]] 符 : [ad-z]( 差 集 ) a 到 z, 并 且 不 包 括 m 到 p: [a-z&&[^m-p]] [a-lq-z]( 差 集 )
左边列指定正则表达式构造,右边列描述每个构造的匹配的条件.
注 意 : " 字 符 类 ( character class) " 这 个 词 中 的 " 类 ( class) " 指 的 并 不 是 一 个 .class 文 件 . 在 正 则 表 达 式 的 语 义 中 , 字 符 类 是 放 在 方 括 号 里 的 字 符 集 , 指定了一些字符中的一个能被给定的字符串所匹配.
3.1
简单类( 简单类(Simple Classes)返回目录 )
字符类最基本的格式是把一些字符放在一对方括号内.例如:正则表达式
[bcr]at 会 匹 配 " bat" , " cat" 或 者 " rat" , 这 是 由 于 其 定 义 了 一 个 字 符 类 ( 接 受 " b" , " c" 或 " r" 中 的 一 个 字 符 ) 作 为 它 的 首 字 符 . Enter your regex: [bcr]at Enter input string to search: bat I found the text "bat" starting at index 0 and ending at index 3. Enter your regex: [bcr]at Enter input string to search: cat I found the text "cat" starting at index 0 and ending at index 3. Enter your regex: [bcr]at Enter input string to search: rat I found the text "rat" starting at index 0 and ending at index 3. Enter your regex: [bcr]at Enter input string to search: hat No match found. 在上面的例子中,在第一个字符匹配字符类中所定义字符中的一个时,整个匹配 就是成功的.
3.1.1
否 定 返回目录
要 匹 配 除 那 些 列 表 之 外 所 有 的 字 符 时 , 可 以 在 字 符 类 的 开 始 处 加 上 ^元 字 符 , 这 种 就 被 称 为 否 定 ( negation) . Enter your regex: [^bcr]at Enter input string to search: bat No match found. Enter your regex: [^bcr]at Ente

r input string to search: cat No match found. Enter your regex: [^bcr]at Enter input string to search: rat No match found. Enter your regex: [^bcr]at Enter input string to search: hat I found the text "hat" starting at index 0 and ending at index 3. 在输入的字符串中的第一个字符不包含在字符类中所定义字符中的一个时,匹配 是成功的.
3.1.2
范 围 返回目录
有 时 会 想 要 定 义 一 个 包 含 值 范 围 的 字 符 类 , 诸 如 , " a 到 h" 的 字 母 或 者 是 " 1 到 5" 的 数 字 . 指 定 一 个 范 围 , 只 要 在 被 匹 配 的 首 字 符 和 末 字 符 间 插 入 -元 字 符 , 比 如 : [1-5]或 者 是 [a-h]. 也 可 以 在 类 里 每 个 的 边 上 放 置 不 同 的 范 围 来 提 高 匹 配 的 可 能 性 , 例 如 : [a-zA-Z]将 会 匹 配 a 到 z( 小 写 字 母 ) 或 者 A 到 Z( 大 写 字 母 ) 中 的 任 何一个字符. 下面是一些范围和否定的例子:
Enter your regex: [a-c] Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1. Enter your regex: [a-c] Enter input string to search: b
I found the text "b" starting at index 0 and ending at index 1. Enter your regex: [a-c] Enter input string to search: c I found the text "c" starting at index 0 and ending at index 1. Enter your regex: [a-c] Enter input string to search: d No match found. Enter your regex: foo[1-5] Enter input string to search: foo1 I found the text "foo1" starting at index 0 and ending at index 4. Enter your regex: foo[1-5] Enter input string to search: foo5 I found the text "foo5" starting at index 0 and ending at index 4. Enter your regex: foo[1-5] Enter input string to search: foo6 No match found. Enter your regex: foo[^1-5] Enter input string to search: foo1 No match found. Enter your regex: foo[^1-5] Enter input string to search: foo6 I found the text "foo6" starting at index 0 and ending at index 4.
3.1.3
并 集 返回目录
可 以 使 用 并 集 ( union) 来 建 一 个 由 两 个 或 两 个 以 上 字 符 类 所 组 成 的 单 字 符 类 . 构 建 一 个 并 集 , 只 要 在 一 个 字 符 类 的 边 上 嵌 套 另 外 一 个 , 比 如 : [0-4[6-8]], 这 种 奇 特 方 式 构 建 的 并 集 字 符 类 , 可 以 匹 配 0, 1, 2, 3, 4, 6, 7, 8 这 几 个 数 字 . Enter your regex: [0-4[6-8]] Enter input string to search: 0 I found the text "0" starting at index 0 and ending at index 1.
Enter your regex: [0-4[6-8]] Enter input string to search: 5 No match found. Enter your regex: [0-4[6-8]] Enter input string to search: 6 I found the text "6" starting at index 0 and ending at index 1. Enter your regex: [0-4[6-8]] Enter input string to search: 8 I found the text "8" starting at index 0 and ending at index 1. Enter your regex: [0-4[6-8]] Enter input string to search: 9 No match found.
3.1.4
交 集 返回目录
建 一 个 仅 仅 匹 配 自 身 嵌 套 类 中 公

共 部 分 字 符 的 字 符 类 时 , 可 以 像 [0-9&&[345]] 中 那 样 使 用 &&. 这 种 方 式 构 建 出 来 的 交 集( intersection)简 单 字 符 类 , 仅 仅 以 匹 配 两 个 字 符 类 中 的 3, 4, 5 共 有 部 分 . Enter your regex: [0-9&&[345]] Enter input string to search: 3 I found the text "3" starting at index 0 and ending at index 1. Enter your regex: [0-9&&[345]] Enter input string to search: 4 I found the text "4" starting at index 0 and ending at index 1. Enter your regex: [0-9&&[345]] Enter input string to search: 5 I found the text "5" starting at index 0 and ending at index 1. Enter your regex: [0-9&&[345]] Enter input string to search: 2 No match found. Enter your regex: [0-9&&[345]] Enter input string to search: 6
No match found. 下面演示两个范围交集的例子: Enter your regex: [2-8&&[4-6]] Enter input string to search: 3 No match found. Enter your regex: [2-8&&[4-6]] Enter input string to search: 4 I found the text "4" starting at index 0 and ending at index 1. Enter your regex: [2-8&&[4-6]] Enter input string to search: 5 I found the text "5" starting at index 0 and ending at index 1. Enter your regex: [2-8&&[4-6]] Enter input string to search: 6 I found the text "6" starting at index 0 and ending at index 1. Enter your regex: [2-8&&[4-6]] Enter input string to search: 7 No match found.
3.1.5
差 集 返回目录
最 后 , 可 以 使 用 差 集 ( subtraction) 来 否 定 一 个 或 多 个 嵌 套 的 字 符 类 , 比 如 : [0-9&&[^345]], 这 个 是 构 建 一 个 匹 配 除 3, 4, 5 之 外 所 有 0 到 9 间 数 字 的 简 单 字符类. Enter your regex: [0-9&&[^345]] Enter input string to search: 2 I found the text "2" starting at index 0 and ending at index 1. Enter your regex: [0-9&&[^345]] Enter input string to search: 3 No match found. Enter your regex: [0-9&&[^345]] Enter input string to search: 4 No match found.
Enter your regex: [0-9&&[^345]] Enter input string to search: 5 No match found. Enter your regex: [0-9&&[^345]] Enter input string to search: 6 I found the text "6" starting at index 0 and ending at index 1. Enter your regex: [0-9&&[^345]] Enter input string to search: 9 I found the text "9" starting at index 0 and ending at index 1. 到此为止,已经涵盖了如何建立字符类的部分.在继续下一节之前,可以试着回 想 一 下 那 张 字符类表.
4
预定义字符类 返回目录
Pattern 的 API 包 有 许 多 有 用 的 预 定 义 字 符 类 ( predefined character
classes) , 提 供 了 常 用 正 则 表 达 式 的 简 写 形 式 .
预定 义字符类
. \d \D \s \S \w \W
任何字符(匹配或者不匹配行结束符) 数 字 字 符 : [0-9] 非 数 字 字 符 : [^0-9] 空 白 字 符 : [\t\n\x0B\f\r] 非 空 白 字 符 : [^\s] 单 词 字 符 : [a-zA-Z_0-9] 非 单 词 字 符 : [^\w] 上 表 中 , 左 列 是 构 造 右 列 字 符 类 的 简 写 形 式 . 例 如 : \d 指

的 是 数 字 范 围( 0~ 9),
\w 指 的 是 单 词 字 符( 任 何 大 小 写 字 母 , 下 划 线 或 者 是 数 字 ). 无 论 何 时 都 有 可 能 使 用 预 定义字符类,它可以使代码更易阅读,更易从难看的字符类中排除错误. 以 反 斜 线 ( \) 开 始 的 构 造 称 为 转 义 构 造 ( escaped constructs) . 回 顾 一 下 在 字
符串 一 节 中 的 转 义 构 造 , 在 那 里 我 们 提 及 了 使 用 反 斜 线 , 以 及 用 于 引 用 的 \Q 和 \E. 在
字符串中使用转义构造,必须在一个反斜线前再增加一个反斜用于字符串的编译,例 如:
001 private final String REGEX = "\\d"; // 单个数字
这 个 例 子 中 \d 是 正 则 表 达 式 , 另 外 的 那 个 反 斜 线 是 用 于 代 码 编 译 所 必 需 的 . 但 是 测试用具读取的表达式,是直接从控制台中输入的,因此不需要那个多出来的反斜 线. 下面的例子说明了预字义字符类的用法:
Enter your regex: . Enter input string to search: @ I found the text "@" starting at index 0 and ending at index 1. Enter your regex: . Enter input string to search: 1 I found the text "1" starting at index 0 and ending at index 1. Enter your regex: . Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1. Enter your regex: \d Enter input string to search: 1 I found the text "1" starting at index 0 and ending at index 1. Enter your regex: \d Enter input string to search: a No match found. Enter your regex: \D Enter input string to search: 1 No match found. Enter your regex: \D Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1.
Enter your regex: \s Enter input string to search: I found the text " " starting at index 0 and ending at index 1. Enter your regex: \s Enter input string to search: a No match found. Enter your regex: \S Enter input string to search: No match found. Enter your regex: \S Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1. Enter your regex: \w Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1. Enter your regex: \w Enter input string to search: ! No match found. Enter your regex: \W Enter input string to search: a No match found. Enter your regex: \W Enter input string to search: ! I found the text "!" starting at index 0 and ending at index 1. 在 开 始 的 三 个 例 子 中 , 正 则 表 达 式 是 简 单 的 , .( " 点 " 元 字 符 ) 表 示 " 任 意 字 符 " , 因 此 , 在 所 有 的 三 个 例 子 ( 随 意 地 选 取 了 " @" 字 符 , 数 字 和 字 母 ) 中 都 是 匹 配 成功的.在接下来的例子中,都使用了预定义字符类表格中的单个正则表达式构造. 你应该可以根据这张表指出前面每个匹配的逻辑: \d 匹 配 数 字 字 符 \s 匹 配 空 白 字 符
\w 匹 配 单 词 字 符 也可以

使用意思正好相反的大写字母: \D 匹 配 非 数 字 字 符 \S 匹 配 非 空 白 字 符 \W 匹 配 非 单 词 字 符
5
量词 返回目录
这 一 节 我 们 来 看 一 下 贪 婪 ( greedy) , 勉 强 ( reluctant) 和 侵 占 ( possessive)
量词,来匹配指定表达式 X 的次数. 量 词 ( quantifiers) 允 许 指 定 匹 配 出 现 的 次 数 , 方 便 起 见 , 当 前 Pattern API 规 范 下 , 描 述 了 贪 婪 , 勉 强 和 侵 占 三 种 量 词 . 首 先 粗 略 地 看 一 下 , 量 词 X?, X??和 X?+都 允许匹配 X 零次或一次,精确地做同样的事情,但它们之间有着细微的不同之处,在 这节结束前会进行说明. 量 贪婪 词 种 类 意 勉强 侵占 匹配 X 零次或 X? X?? X?+ 一次 匹配 X 零次或 X* X*? X*+ 多次 匹配 X 一次或 X+ X+? X++ 多次 匹配 X n 次 匹配 X至少 n X{n,} X{n,}? X{n,}+ 次 匹配 X 至少 n X{n,m} X{n,m}? X{n,m}+ 次,但不多于 m 义
X{n}
X{n}?
X{n}+
次 那 我 们 现 在 就 从 贪 婪 量 词 开 始 , 构 建 三 个 不 同 的 正 则 表 达 式 : 字 母 a 后 面 跟 着 ?, *和 +. 接 下 来 看 一 下 , 用 这 些 表 达 式 来 测 试 输 入 的 字 符 串 是 空 字 符 串 时 会 发 生 些 什 么:
Enter your regex: a? Enter input string to search: I found the text "" starting at index 0 and ending at index 0. Enter your regex: a* Enter input string to search: I found the text "" starting at index 0 and ending at index 0. Enter your regex: a+ Enter input string to search: No match found.
5.1
零长度匹配返回目录
在 上 面 的 例 子 中 , 开 始 的 两 个 匹 配 是 成 功 的 , 这 是 因 为 表 达 式 a?和 a*都 允 许 字 符
出现零次.就目前而言,这个例子不像其他的,也许你注意到了开始和结束的索引都 是 0. 输 入 的 空 字 符 串 没 有 长 度 , 因 此 该 测 试 简 单 地 在 索 引 0 上 匹 配 什 么 都 没 有 , 诸 如 此 类 的 匹 配 称 之 为 零 长 度 匹 配 ( zero-length matches) . 零 长 度 匹 配 会 出 现 在 以 下 几种情况:输入空的字符串,在输入字符串的开始处,在输入字符串最后字符的后 面,或者是输入字符串中任意两个字符之间.由于它们开始和结束的位置有着相同的 索引,因此零长度匹配是容易被发现的. 我 们 来 看 一 下 关 于 零 长 度 匹 配 更 多 的 例 子 . 把 输 入 的 字 符 串 改 为 单 个 字 符 " a" , 你会注意到一些有意思的事情:
Enter your regex: a? Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1. I found the text "" starting at index 1 and ending at index 1.
Enter your regex: a* Enter input string to search: a I found the text "a" starting at index 0 and ending at index 1. I found the text "" starting at index 1 and ending at index 1. Enter your regex: a+ Enter input string to search:

a I found the text "a" starting at index 0 and ending at index 1. 所 有 的 三 个 量 词 都 是 用 来 寻 找 字 母 " a" 的 , 但 是 前 面 两 个 在 索 引 1 处 找 到 了 零 长度匹配,也就是说,在输入字符串最后一个字符的后面.回想一下,匹配把字符 " a" 看 作 是 位 于 索 引 0 和 索 引 1 之 间 的 单 元 格 中 , 并 且 测 试 用 具 一 直 循 环 下 去 直 到 不再有匹配为止.依赖于所使用的量词不同,最后字符后面的索引"什么也没有"的 存在可以或者不可以触发一个匹配. 现 在 把 输 入 的 字 符 串 改 为 一 行 5 个 " a" 时 , 会 得 到 下 面 的 结 果 :
Enter your regex: a? Enter input string to search: aaaaa I found the text "a" starting at index 0 and ending I found the text "a" starting at index 1 and ending I found the text "a" starting at index 2 and ending I found the text "a" starting at index 3 and ending I found the text "a" starting at index 4 and ending I found the text "" starting at index 5 and ending
at at at at at at
index index index index index index
1. 2. 3. 4. 5. 5.
Enter your regex: a* Enter input string to search: aaaaa I found the text "aaaaa" starting at index 0 and ending at index 5. I found the text "" starting at index 5 and ending at index 5. Enter your regex: a+ Enter input string to search: aaaaa I found the text "aaaaa" starting at index 0 and ending at index 5. 在 " a" 出 现 零 次 或 一 次 时 , 表 达 式 a?寻 找 到 所 匹 配 的 每 一 个 字 符 . 表 达 式 a*找
到 了 两 个 单 独 的 匹 配 : 第 一 次 匹 配 到 所 有 的 字 母 " a" , 然 后 是 匹 配 到 最 后 一 个 字 符 后 面 的 索 引 5. 最 后 , a+匹 配 了 所 有 出 现 的 字 母 " a" , 忽 略 了 在 最 后 索 引 处 " 什 么 都 没 有"的存在. 在 这 里 , 你 也 许 会 感 到 疑 惑 , 开 始 的 两 个 量 词 在 遇 到 除 了 " a" 的 字 母 时 会 有 什 么 结 果 . 例 如 , 在 " ababaaaab" 中 遇 到 了 字 母 " b" 会 发 生 什 么 呢 ? 下面我们来看一下:
Enter your regex: a? Enter input string to search: ababaaaab I found the text "a" starting at index 0 and ending I found the text "" starting at index 1 and ending I found the text "a" starting at index 2 and ending I found the text "" starting at index 3 and ending I found the text "a" starting at index 4 and ending I found the text "a" starting at index 5 and ending I found the text "a" starting at index 6 and ending I found the text "a" starting at index 7 and ending I found the text "" starting at index 8 and ending I found the text "" starting at index 9 and ending
at at at at at at at at at at
index index index index index index index index index index
1. 1. 3. 3. 5. 6. 7. 8. 8. 9.
Enter your regex: a* Enter input string to search: ababaaaab I found the text "a" starting at index 0 and ending at I found the text "" starting a

t index 1 and ending at I found the text "a" starting at index 2 and ending at I found the text "" starting at index 3 and ending at I found the text "aaaa" starting at index 4 and ending 8. I found the text "" starting at index 8 and ending at I found the text "" starting at index 9 and ending at
index 1. index 1. index 3. index 3. at index index 8. index 9.
Enter your regex: a+ Enter input string to search: ababaaaab I found the text "a" starting at index 0 and ending at index 1. I found the text "a" starting at index 2 and ending at index 3. I found the text "aaaa" starting at index 4 and ending at index 8.
即 使 字 母 " b" 在 单 元 格 1, 3, 8 中 出 现 , 但 在 这 些 位 置 上 的 输 出 报 告 了 零 长 度 匹 配 . 正 则 表 达 式 a?不 是 特 意 地 去 寻 找 字 母 " b" , 它 仅 仅 是 去 找 字 母 " a" 存 在 或 者 其 中 缺 少 的 . 如 果 量 词 允 许 匹 配 " a" 零 次 , 任 何 输 入 的 字 符 不 是 " a" 时 将 会 作 为 零 长度匹配.在前面的例子中,根据讨论的规则保证了 a 被匹配. 对于要精确地匹配一个模式 n 次时,可以简单地在一对花括号内指定一个数值:
Enter your regex: a{3} Enter input string to search: aa No match found. Enter your regex: a{3} Enter input string to search: aaa I found the text "aaa" starting at index 0 and ending at index 3. Enter your regex: a{3} Enter input string to search: aaaa I found the text "aaa" starting at index 0 and ending at index 3. 这 里 , 正 则 表 确 定 式 a{3}在 一 行 中 寻 找 连 续 出 现 三 次 的 字 母 " a" . 第 一 次 测 试 失 败的原由在于,输入的字符串没有足够的 a 用来匹配;第二次测试输出的字符串正好 包 括 了 三 个 " a" , 触 发 了 一 次 匹 配 ; 第 三 次 测 试 也 触 发 了 一 次 匹 配 , 这 是 由 于 在 输 出 的 字 符 串 的 开 始 部 分 正 好 有 三 个 " a" . 接 下 来 的 事 情 与 第 一 次 的 匹 配 是 不 相 关 的 , 如 果这个模式将在这一点后继续出现,那它将会触发接下来的匹配: Enter your regex: a{3} Enter input string to search: aaaaaaaaa I found the text "aaa" starting at index 0 and ending at index 3. I found the text "aaa" starting at index 3 and ending at index 6. I found the text "aaa" starting at index 6 and ending at index 9. 对 于 需 要 一 个 模 式 出 现 至 少 n 次 时 , 可 以 在 这 个 数 字 后 面 加 上 一 个 逗 号 ( ,) : Enter your regex: a{3,} Enter input string to search: aaaaaaaaa I found the text "aaaaaaaaa" starting at index 0 and ending at index 9.
输 入 一 样 的 字 符 串 , 这 次 测 试 仅 仅 找 到 了 一 个 匹 配 , 这 是 由 于 一 个 中 有 九 个 " a" 满 足 了 " 至 少 " 三 个 " a" 的 要 求 . 最后,对于指定出现次数的上限,可以在花括号添加第二个数字.
Enter your regex: a{3,6} // 寻找一行中至少连续出现 3 个(但

不多于 6 个) "a" Enter input string to search: aaaaaaaaa I found the text "aaaaaa" starting at index 0 and ending at index 6. I found the text "aaa" starting at index 6 and ending at index 9. 这里,第一次匹配在 6 个字符的上限时被迫终止了.第二个匹配包含了剩余的三 个 a( 这 是 匹 配 所 允 许 最 小 的 字 符 个 数 ). 如 果 输 入 的 字 符 串 再 少 掉 一 个 字 母 , 这 时 将 不 会 有 第 二 个 匹 配 , 之 后 仅 剩 余 两 个 a.
5.2
捕获组和字符类中的量词返回目录
到目前为止,仅仅测试了输入的字符串包括一个字符的量词.实际上,量词仅仅
可 能 附 在 一 个 字 符 后 面 一 次 , 因 此 正 则 表 达 式 abc+的 意 思 就 是 " a 后 面 接 着 b, 再 接 着 一 次 或 者 多 次 的 c" , 它 的 意 思 并 不 是 指 abc 一 次 或 者 多 次 . 然 而 , 量 词 也 可 能 附 在 字 符 类 和 捕 获 组 的 后 面 , 比 如 , [abc]+表 示 一 次 或 者 多 次 的 a 或 b 或 c, (abc)+表 示 一 次 或 者 多 次 的 " abc" 组 . 我 们 来 指 定 (dog)组 在 一 行 中 三 次 进 行 说 明 .
Enter your regex: (dog){3} Enter input string to search: dogdogdogdogdogdog I found the text "dogdogdog" starting at index 0 and ending at index 9. I found the text "dogdogdog" starting at index 9 and ending at index 18. Enter your regex: dog{3} Enter input string to search: dogdogdogdogdogdog
No match found. 上面的第一个例子找到了三个匹配,这是由于量词用在了整个捕获组上.然而, 把 圆 括 号 去 掉 , 这 时 的 量 词 {3}现 在 仅 用 在 了 字 母 " g" 上 , 从 而 导 致 这 个 匹 配 失 败 . 类似地,也能把量词应用于整个字符类:
Enter your regex: [abc]{3} Enter input string to search: abccabaaaccbbbc I found the text "abc" starting at index 0 and ending at index 3. I found the text "cab" starting at index 3 and ending at index 6. I found the text "aaa" starting at index 6 and ending at index 9. I found the text "ccb" starting at index 9 and ending at index 12. I found the text "bbc" starting at index 12 and ending at index 15. Enter your regex: abc{3} Enter input string to search: abccabaaaccbbbc No match found. 上 面 的 第 一 个 例 子 中 , 量 词 {3}应 用 在 了 整 个 字 符 类 上 , 但 是 第 二 个 例 子 这 个 量 词 仅 用 在 字 母 " c" 上 .
5.3
贪婪, 贪婪,勉强和侵占量词间的不同返回目录
在贪婪,勉强和侵占三个量词间有着细微的不同. 贪婪量词之所以称之为"贪婪的",这是由于它们强迫匹配器读入(或者称之为吃
掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入 的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进 行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了.

赖于在表达式中 使用的量词,最终它将尝试地靠着 1 或 0 个字符的匹配. 但是,勉强量词采用相反的途径:从输入字符串的开始处开始,因此每次勉强地 吞噬一个字符来寻找匹配,最终它们会尝试整个输入的字符串. 最后,侵占量词始终是吞掉整个输入的字符串,尝试着一次(仅有一次)匹配.不 像贪婪量词那样,侵占量词绝不会回退,即使这样做是允许全部的匹配成功. 为 了 说 明 一 下 , 看 看 输 入 的 字 符 串 是 xfooxxxxxxfoo 时 .
Enter your regex: .*foo
// 贪婪量词
Enter input string to search: xfooxxxxxxfoo I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13. Enter your regex: .*?foo // 勉强量词
Enter input string to search: xfooxxxxxxfoo I found the text "xfoo" starting at index 0 and ending at index 4. I found the text "xxxxxxfoo" starting at index 4 and ending at index 13. Enter your regex: .*+foo // 侵占量词 Enter input string to search: xfooxxxxxxfoo No match found. 第 一 个 例 子 使 用 贪 婪 量 词 .*, 寻 找 紧 跟 着 字 母 " f" " o" " o" 的 " 任 何 东 西 " 零 次 或 者 多 次 . 由 于 量 词 是 贪 婪 的 , 表 达 式 的 .*部 分 第 一 次 " 吃 掉 " 整 个 输 入 的 字 符 串.在这一点,全部表达式不能成功地进行匹配,这是由于最后三个字母 ( " f" " o" " o" ) 已 经 被 消 耗 掉 了 . 那 么 匹 配 器 会 慢 慢 地 每 次 回 退 一 个 字 母 , 直 到 返 还 的 " foo" 在 最 右 边 出 现 , 这 时 匹 配 成 功 并 且 搜 索 终 止 . 然而,第二个例子采用勉强量词,因此通过首次消耗"什么也没有"作为开始. 由 于 " foo" 并 没 有 出 现 在 字 符 串 的 开 始 , 它 被 强 迫 吞 掉 第 一 个 字 母 " x" ) 在 0 和 ( , 4 处触发了第一个匹配.测试用具会继续处理,直到输入的字符串耗尽为止.在 4 和 13 找 到 了 另 外 一 个 匹 配 . 第三个例子的量词是侵占,所以在寻找匹配时失败了.在这种情况下,整个输入 的 字 符 串 被 .*+消 耗 了 , 什 么 都 没 有 剩 下 来 满 足 表 达 式 末 尾 的 " foo" . 你可以在想抓取所有的东西,且决不回退的情况下使用侵占量词,在这种匹配不 是立即被发现的情况下,它将会优于等价的贪婪量词.
6
捕获组 返回目录
在上一节中,学习了每次如何把量词放在一个字符,字符类或者捕获组中.到目 前为止,还没有详细地讨论过捕获组的概念. 捕 获 组 ( capturing group) 是 将 多 个 字 符 作 为 单 独 的 单 元 来 对 待 的 一 种 方 式 . 构 建 它 们 可 以 通 过 把 字 符 放 在 一 对 圆 括 号 中 而 成 为 一 组 . 例 如 , 正 则 表 达 式 (dog)建 了 单 个 的 组 , 包 括 字 符 " d" " o" 和 " g" . 匹 配 捕 获 组 输 入 的 字 符 串 部 分 将 会 存 放 于 内 存 中 , 稍 后 通 过 反 向 引

用 再 次 调 用 . ( 在 6.2 节 中 将 会 讨 论 反 向 引 用 )
6.1
编号方式返回目录
在 Pattern 的 API 描 述 中 , 捕 获 组 通 过 从 左 至 右 计 算 开 始 的 圆 括 号 进 行 编 号 .
例 如 , 在 表 达 式 ((A)(B(C)))中 , 有 下 面 的 四 组 : 1. ((A)(B(C))) 2. (A) 3. (B(C)) 4. (C) 要 找 出 当 前 的 表 达 式 中 有 多 少 组 , 通 过 调 用 Matcher 对 象 的 groupCount 方 法 . groupCount 方 法 返 回 int 类 型 值 , 表 示 当 前 Matcher 模 式 中 捕 获 组 的 数 量 . 例 如 , groupCount 返 回 4 时 , 表 示 模 式 中 包 含 有 4 个 捕 获 组 . 有 一 个 特 别 的 组 ——组 0, 它 表 示 整 个 表 达 式 . 这 个 组 不 包 括 在 groupCount 的 报 告 范 围 内 . 以 (?开 始 的 组 是 纯 粹 的 非 捕 获 组( non-capturing group), 它 不 捕 获 文 本 , 也 不 作 为 组 总 数 而 计 数 . ( 可 以 看 8 Pattern 类的方法 一 节 中 非 捕 获 组 的 例 子 . ) Matcher 中 的 一 些 方 法 , 可 以 指 定 int 类 型 的 特 定 组 号 作 为 参 数 , 因 此 理 解 组 是 如何编号的是尤为重要的. public int start(int group): 返 回 之 前 的 匹 配 操 作 期 间 , 给 定 组 所 捕 获 的 子 序 列的初始索引. public int end(int group): 返 回 之 前 的 匹 配 操 作 期 间 , 给 定 组 所 捕 获 子 序 列 的 最 后 字 符 索 引 加 1. public String group (int group): 返 回 之 前 的 匹 配 操 作 期 间 , 通 过 给 定 组 而 捕
获的输入子序列.
6.2
反向引用返回目录
匹 配 输 入 字 符 串 的 捕 获 组 部 分 会 存 放 在 内 存 中 , 通 过 反 向 引 用 ( backreferences)
稍 后 再 调 用 . 在 正 则 表 达 式 中 , 反 向 引 用 使 用 反 斜 线 ( \) 后 跟 一 个 表 示 需 要 再 调 用 组 号 的 数 字 来 表 示 . 例 如 , 表 达 式 (\d\d)定 义 了 匹 配 一 行 中 的 两 个 数 字 的 捕 获 组 , 通 过 反 向 引 用 \1, 表 达 式 稍 候 会 被 再 次 调 用 . 匹 配 两 个 数 字 , 且 后 面 跟 着 两 个 完 全 相 同 的 数 字 时 , 就 可 以 使 用 (\d\d)\1 作 为 正 则表达式:
Enter your regex: (\d\d)\1 Enter input string to search: 1212 I found the text "1212" starting at index 0 and ending at index 4. 如果更改最后的两个数字,这时匹配就会失败:
Enter your regex: (\d\d)\1 Enter input string to search: 1234 No match found. 对于嵌套的捕获组而言,反向引用采用完全相同的方式进行工作,即指定一个反 斜线加上需要被再次调用的组号.
7
边界匹配器 返回目录
就目前而言,我们的兴趣在于指定输入字符串中某些位置是否有匹配,还没有考
虑到字符串的匹配产生在什么地方. 通 过 指 定 一 些 边 界 匹 配 器 ( boundary matchers) 的 信 息 , 可 以 使 模 式 匹 配 更 为 精

确.比如说你对某个特定的单词感兴趣,并且它只出现在行首或者是行尾时.又或者 你 想 知 道 匹 配 发 生 在 单 词 边 界 ( word boundary) , 或 者 是 上 一 个 匹 配 的 尾 部 . 下表中列出了所有的边界匹配器及其说明.
边界 匹配器
^ $ \b \B \A \G \Z \z
行首 行尾 单词边界 非单词边界 输入的开头 上一个匹配的结尾 输入的结尾,仅用于最后的结束符(如果有的话) 输入的结尾 接 下 来 的 例 子 中 , 说 明 了 ^和 $边 界 匹 配 器 的 用 法 . 注 意 上 表 中 , ^匹 配 行 首 , $匹
配行尾.
Enter your regex: ^dog$ Enter input string to search: dog I found the text "dog" starting at index 0 and ending at index 3. Enter your regex: ^dog$ Enter input string to search: No match found.
dog
Enter your regex: \s*dog$ Enter input string to search: dog I found the text " dog" starting at index 0 and ending at index 15. Enter your regex: ^dog\w* Enter input string to search: dogblahblah I found the text "dogblahblah" starting at index 0 and ending at index 11. 第一个例子的匹配是成功的,这是因为模式占据了整个输入的字符串.第二个例 子失败了,是由于输入的字符串在开始部分包含了额外的空格.第三个例子指定的表 达 式 是 不 限 的 空 格 , 后 跟 着 在 行 尾 的 dog. 第 四 个 例 子 , 需 要 dog 放 在 行 首 , 后 面 跟 的是不限数量的单词字符.
对于检查一个单词开始和结束的边界模式(用于长字符串里子字符串),这时可以 在 两 边 使 用 \b, 例 如 \bdog\b. Enter your regex: \bdog\b Enter input string to search: The dog plays in the yard. I found the text "dog" starting at index 4 and ending at index 7. Enter your regex: \bdog\b Enter input string to search: The doggie plays in the yard. No match found. 对 于 匹 配 非 单 词 边 界 的 表 达 式 , 可 以 使 用 \B 来 代 替 :
Enter your regex: \bdog\B Enter input string to search: The dog plays in the yard. No match found. Enter your regex: \bdog\B Enter input string to search: The doggie plays in the yard. I found the text "dog" starting at index 4 and ending at index 7. 对 于 需 要 匹 配 仅 出 现 在 前 一 个 匹 配 的 结 尾 , 可 以 使 用 \G:
Enter your regex: dog Enter input string to search: dog dog I found the text "dog" starting at index 0 and ending at index 3. I found the text "dog" starting at index 4 and ending at index 7. Enter your regex: \Gdog Enter input string to search: dog dog I found the text "dog" starting at index 0 and ending at index 3. 这 里 的 第 二 个 例 子 仅 找 到 了 一 个 匹 配 , 这 是 由 于 第 二 次 出 现 的 " dog" 不 是 在 前 一 个 匹 配 结 尾 的 开 始 . [7]
8
Pattern 类的方法 返回目录
到 目 前 为 止 , 仅 使 用 测 试 用 具 来 建 立 最 基 本 的 Pattern 对 象 . 在 这 一 节 中 ,

我 们
将探讨一些诸如使用标志构建模式,使用内嵌标志表达式等高级的技术.同时也探讨 了一些目前还没有讨论过的其他有用的方法.
8.1
使用标志构建模式返回目录
Pattern 类 定 义 了 备 用 的 compile 方 法 , 用 于 接 受 影 响 模 式 匹 配 方 式 的 标 志 集 .
标志参数是一个位掩码,可以是下面公共静态字段中的任意一个:
Pattern.CANON_EQ
启用规范等价.在指定此标志后,当且仅当在其完整的规范分解匹配时,两个字 符 被 视 为 匹 配 . 例 如 , 表 达 式 a\u030A [8]在 指 定 此 标 志 后 , 将 匹 配 字 符 串 " \u00E5" ( 即 字 符 ). 默 认 情 况 下 , 匹 配 不 会 采 用 规 范 等 价 . 指 定 此 标 志 可 能 会 对 性 能 会 有 一 定的影响.
Pattern.CASE_INSENSITIVE
启 用 不 区 分 大 小 写 匹 配 . 默 认 情 况 下 , 仅 匹 配 US-ASCII 字 符 集 中 的 字 符 . Unicode 感 知 Unicode-aware) 不 区 分 大 小 写 匹 配 , 可 以 通 过 指 定 UNICODE_CASE 标 ( 的 志 连 同 此 标 志 来 启 用 . 不 区 分 大 小 写 匹 配 也 能 通 过 内 嵌 标 志 表 达 式 (?i)来 启 用 . 指 定 此标志可能会对性能会有一定的影响.
https://www.wendangku.net/doc/7617477729.html,MENTS
模 式 中 允 许 存 在 空 白 和 注 释 . 在 这 种 模 式 下 , 空 白 和 以 #开 始 的 直 到 行 尾 的 内 嵌 注 释 会 被 忽 略 . 注 释 模 式 也 能 通 过 内 嵌 标 志 表 达 式 (?x)来 启 用 .
Pattern.DOTALL
启 用 dotall 模 式 . 在 dotall 模 式 下 , 表 达 式 .匹 配 包 括 行 结 束 符 在 内 的 任 意 字 符 . 默 认 情 况 下 , 表 达 式 不 会 匹 配 行 结 束 符 . dotall 模 式 也 通 过 内 嵌 标 志 表 达 式 (?x) 来 启 用 . [ s 是 " 单 行 ( single-line) " 模 式 的 助 记 符 , 与 Perl 中 的 相 同 . ]
Pattern.LITERAL
启用模式的字面分析.指定该标志后,指定模式的输入字符串作为字面上的字符
序列来对待.输入序列中的元字符和转义字符不具有特殊的意义了. CASE_INSENSITIVE 和 UNICODE_CASE 与 此 标 志 一 起 使 用 时 , 会 对 匹 配 产 生 一 定 的 影 响.其他的标志就变得多余了.启用字面分析没有内嵌标志表达式.
Pattern.MULTILINE
启 用 多 行 ( multiline) 模 式 . 在 多 行 模 式 下 , 表 达 式 ^和 $分 别 匹 配 输 入 序 列 行 结 束符前面和行结束符的前面.默认情况下,表达式仅匹配整个输入序列的开始和结 尾 . 多 行 模 式 也 能 通 过 内 嵌 标 志 表 达 式 (?m)来 启 用 .
Pattern.UNICODE_CASE
启 用 可 折 叠 感 知 Unicode( Unicode-aware case folding) 大 小 写 . 在 指 定 此 标 志 后 , 需 要 通 过 CASE_INSENSITIVE 标 志 来 启 用 , 不 区 分 大 小 写 区 配 将 在 Unicode 标 准 的 意 义 上 来 完 成 . 默 认 情 况 下

, 不 区 分 大 小 写 匹 配 仅 匹 配 US-ASCII 字 符 集 中 的 字 符 . 可 折 叠 感 知 Unicode 大 小 写 也 能 通 过 内 嵌 标 志 表 达 式 (?u)来 启 用 . 指 定 此 标 志 可 能会对性能会有一定的影响.
Pattern.UNIX_LINES
启 用 Unix 行 模 式 . 在 这 种 模 式 下 , ., ^和 $的 行 为 仅 识 别 " \n" 的 行 结 束 符 . Unix 行 模 式 可 以 通 过 内 嵌 标 志 表 达 式 (?d)来 启 用 . 接 下 来 , 将 修 改 测 试 用 具 RegexTestHarness.java, 用 于 构 建 不 区 分 大 小 写 匹 配 的 模 式. 首 先 , 修 改 代 码 去 调 用 complie 的 另 外 一 个 备 用 的 方 法 :
001 002 003 004 Pattern pattern = https://www.wendangku.net/doc/7617477729.html,pile( console.readLine("%nEnter your regex: "), Pttern.CASE_INSENSITIVE );
编译并运行这个测试用具,会得出下面的结果:
Enter your regex: dog Enter input string to search: DoGDOg I found the text "DoG" starting at index 0 and ending at index 3. I found the text "DOg" starting at index 3 and ending at index 6. 正 如 你 所 看 到 的 , 不 管 是 否 大 小 写 , 字 符 串 字 面 上 是 " dog" 的 都 产 生 了 匹 配 . 使 用 多 个 标 志 来 编 译 一 个 模 式 , 使 用 按 位 或 操 作 符 " |" 分 隔 各 个 标 志 . 为 了 更 清 晰 地 说 明 , 下 面 的 示 例 代 码 使 用 硬 编 码 ( hardcode) 的 方 式 , 来 取 代 控 制 台 中 的 读 取 :
001 pattern = https://www.wendangku.net/doc/7617477729.html,pile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES);
也 可 以 使 用 一 个 int 类 型 的 变 量 来 代 替 :
001 002 final int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; Pattern pattern = https://www.wendangku.net/doc/7617477729.html,pile("aa", flags);
8.2
内嵌标志表达式返回目录
使 用 内 嵌 标 志 表 达 式 ( embedded flag expressions) 也 可 以 启 用 不 同 的 标 志 . 对
于 两 个 参 数 的 compile 方 法 , 内 嵌 标 志 表 达 式 是 可 选 的 , 因 为 它 在 自 身 的 正 则 表 达 式 中 被 指 定 了 . 下 面 的 例 子 使 用 最 初 的 测 试 用 具( RegexTestHarness.java), 使 用 内 嵌 标 志 表 达 式 (?i)来 启 用 不 区 分 大 小 写 的 匹 配 .
Enter your regex: (?i)foo Enter input string to search: FOOfooFoOfoO I found the text "FOO" starting at index 0 and ending at index 3. I found the text "foo" starting at index 3 and ending at index 6. I found the text "FoO" starting at index 6 and ending at index 9. I found the text "foO" starting at index 9 and ending at index 12. 所有匹配无关大小写都一次次地成功了. 内 嵌 标 志 表 达 式 所 对 应 Pattern 的 公 用 的 访 问 字 段 表 示 如 下 表 : 常 量 等价的内嵌标志表达式
Pattern.CANON_EQ Pattern.CASE_INSENSITIVE https://www.wendangku.net/doc/7617477729.html,MENTS Pattern.MULTILINE Pattern.DOTALL Pattern.LITERAL Pattern.UNICODE_CASE Pattern.UNIX_LINES
没有 (?i) (?x) (?m) (?s) 没有 (?u) (?d)
8.3
使

用 matches(String, CharSequence) 方法返回目录
Pattern 类 定 义 了 一 个 方 便 的 matches 方 法 , 用 于 快 速 地 检 查 模 式 是 否 表 示 给 定
的 输 入 字 符 串 . 与 使 用 所 有 的 公 共 静 态 方 法 一 样 , 应 该 通 过 它 的 类 名 来 调 用 matches 方 法 , 诸 如 Pattern.matches("\\d","1");. 这 个 例 子 中 , 方 法 返 回 true, 这 是 由 于 数 字 " 1" 匹 配 了 正 则 表 达 式 \d.
8.4
使用 split(String) 方法返回目录
split 方 法 是 一 个 重 要 的 工 具 , 用 于 收 集 依 赖 于 被 匹 配 的 模 式 任 一 边 的 文 本 . 如
下 面 的 SplitDemo.java 所 示 , split 方 法 能 从 " one:two:three:four:five" 字 符 串 中 解 析 出 " one two three four five" 单 词 :
import java.util.regex.Pattern; public class SplitDemo { private static final String REGEX = ":"; private static final String INPUT = "one:two:three:four:five"; public static void main(String[] args) { Pattern p = https://www.wendangku.net/doc/7617477729.html,pile(REGEX); String[] items = p.split(INPUT); for(String s : items) { System.out.println(s); } }
}
输出:
one two three four five 简 而 言 之 , 已 经 使 用 冒 号 ( :) 取 代 了 复 杂 的 正 则 表 达 式 匹 配 字 符 串 文 字 . 以 后 仍 会 使 用 Pattern 和 Matcher 对 象, 也 能 使 用 split 得 到 位 于 任 意 正 则 表 达 式 各 边 的 文 本 . 下 面 的 SplitDemo2.java 是 个 一 样 的 例 子 , 使 用 数 字 作 为 split 的 参 数 :
import java.util.regex.Pattern; public class SplitDemo2 { private static final String REGEX = "\\d"; private static final String INPUT = "one9two4three7four1five"; public static void main(String[] args) { Pattern p = https://www.wendangku.net/doc/7617477729.html,pile(REGEX); String[] items = p.split(INPUT); for(String s : items) { System.out.println(s); } } }
输出:
one two three four five
8.5
其他有用的方法返回目录
你可以从下面的方法中找到比较好用的方法: public static String quote(String s) [9]: 返 回 指 定 字 符 串 字 面 模 式 的 字 符 串 . 此 方 法 会 产 生 一 个 字 符 串 , 能 被 用 于 构 建 一 个 与 字 符 串 s 匹 配 的 Pattern, 好 像 它 是 一个字面上的模式.输入序列中的元字符和转义序列将没有特殊的意义了. public String toString(): 返 回 这 个 模 式 的 字 符 串 表 现 形 式 . 这 是 一 个 编 译 过 的 模式中的正则表达式.
8.6
在 https://www.wendangku.net/doc/7617477729.html,ng.String 中等价的 Pattern 方法返回目录
https://www.wendangku.net/doc/7617477729.html,ng.String 通 过 模 拟 java.util.regex.Pattern 行 为 的 几 个 方 法 , 也 可
以 支 持 正 则 表 达 式 . 方 便 起 见 , 下 面 主 要 摘 录 了 出 现 在 API 关 键 的 方 法 . public boolean matches(String regex): 告 知 字 符 串 是 否 匹 配 给 定 的 正 则 表 达 式 . 调 用 str.matches(regex)方 法 所 产 生 的 结 果 与 作 为

表 达 式 的 Pattern.matches(regex, str)的 结 果 是 完 全 一 致 . public String[] split(String regex, int limit): 依 照 匹 配 给 定 的 正 则 表 达 式 来 拆 分 字 符 串 . 调 用 str.split(regex, n)方 法 所 产 生 的 结 果 与 作 为 表 达 式 的 https://www.wendangku.net/doc/7617477729.html,pile(regex).split(str, n) 的 结 果 完 全 一 致 . public String[] split(String regex): 依 照 匹 配 给 定 的 正 则 表 达 式 来 拆 分 字 符 串 . 这 个 方 法 与 调 用 两 个 参 数 的 split 方 法 是 相 同 的 , 第 一 个 参 数 使 用 给 定 的 表 达 式 , 第 二 个 参 数 限 制 为 0. 在 结 果 数 组 中 不 包 括 尾 部 的 空 字 符 串 . 还 有 一 个 替 换 方 法 , 把 一 个 CharSequence 替 换 成 另 外 一 个 : public String replace(CharSequence target,CharSequence replacement): 将 字符串中每一个匹配替换匹配字面目标序列的子字符串,替换成指定的字面替换序 列 . 这 个 替 换 从 字 符 串 的 开 始 处 理 直 至 结 束 , 例 如 , 把 字 符 串 " aaa" 中 的 " aa" 替 换 成 " b" , 结 果 是 " ba" , 而 不 是 " ab" .
9
Matcher 类的方法 返回目录
在 这 一 节 中 来 看 看 Matcher 类 中 其 他 一 些 有 用 的 方 法 . 方 便 起 见 , 下 面 列 出 的 方
法是按照功能来分组的.
索引方法
索 引 方 法 ( index methods) 提 供 了 一 些 正 好 在 输 入 字 符 串 中 发 现 匹 配 的 索 引 值 : public int start(): 返 回 之 前 匹 配 的 开 始 索 引 . public int start(int group): 返 回 之 前 匹 配 操 作 中 通 过 给 定 组 所 捕 获 序 列 的 开 始索引. public int end(): 返 回 最 后 匹 配 字 符 后 的 偏 移 量 . public int end(int group): 返 回 之 前 匹 配 操 作 中 通 过 给 定 组 所 捕 获 序 列 的 最 后 字符之后的偏移量.
研究方法
研 究 方 法 ( study methods) 回 顾 输 入 的 字 符 串 , 并 且 返 回 一 个 用 于 指 示 是 否 找 到 模式的布尔值. public boolean lookingAt(): 尝 试 从 区 域 开 头 处 开 始 , 输 入 序 列 与 该 模 式 匹 配 . public boolean find(): 尝 试 地 寻 找 输 入 序 列 中 , 匹 配 模 式 的 下 一 个 子 序 列 . public boolean find(int start): 重 置 匹 配 器 , 然 后 从 指 定 的 索 引 处 开 始 , 尝 试 地寻找输入序列中,匹配模式的下一个子序列. public boolean matches(): 尝 试 将 整 个 区 域 与 模 式 进 行 匹 配
替换方法
替 换 方 法( replacement methods)用 于 在 输 入 的 字 符 串 中 替 换 文 本 有 用 处 的 方 法 . public Matcher appendReplacement(StringBuffer sb, String replacement): 实现非结尾处的增加和替换操作. public StringBuffer appendTail(StringBuffer sb): 实 现 结 尾 处 的 增 加 和 替 换 操作. public String replaceAll(String replacement): 使 用 给 定 的 替 换 字 符 串

相关文档