快速入门
教程
工具和语言
示例
参考
书籍评论
正则表达式工具
grep
PowerGREP
RegexBuddy
RegexMagic
通用应用程序
EditPad Lite
EditPad Pro
语言和库
Boost
Delphi
GNU (Linux)
Groovy
Java
JavaScript
.NET
PCRE (C/C++)
PCRE2 (C/C++)
Perl
PHP
POSIX
PowerShell
Python
R
Ruby
std::regex
Tcl
VBScript
Visual Basic 6
wxWidgets
XML Schema
Xojo
XQuery 和 XPath
XRegExp
数据库
MySQL
Oracle
PostgreSQL
本网站上的更多内容
简介
正则表达式快速入门
正则表达式教程
替换字符串教程
应用程序和语言
正则表达式示例
正则表达式参考
替换字符串参考
书籍评论
可打印 PDF
关于本网站
RSS Feed 和博客
RegexBuddy—The best regex editor and tester for Java developers!

在 Java 中使用正则表达式

Java 4 (JDK 1.4) 及更高版本通过标准 java.util.regex 包全面支持正则表达式。由于 Java 长期以来缺少正则表达式包,因此还有许多可用于 Java 的第三方正则表达式包。我将只讨论现在是 JDK 一部分的 Sun 正则表达式库。它的质量非常好,优于大多数第三方包。除非您需要支持 JDK 的较旧版本,否则 java.util.regex 包是您的不二之选。

Java 5 修复了一些错误,并增加了对 Unicode 块 的支持。Java 6 修复了更多错误,但没有添加任何功能。Java 7 添加了 命名捕获Unicode 脚本。Java 13 允许在 后向查找 中使用无限量词。

String 类的快速正则表达式方法

Java String 类有几个方法允许您使用正则表达式对该字符串执行操作,并且代码量极少。缺点是您无法指定“不区分大小写”或“点匹配换行符”等选项。出于性能原因,如果您将经常使用相同的正则表达式,也不应使用这些方法。

myString.matches("regex") 根据字符串是否完全匹配正则表达式返回 true 或 false。请务必记住,只有当整个字符串匹配时,String.matches() 才返回 true。换句话说,“regex”的应用方式就像您使用字符串开头和结尾锚点编写“^regex$”一样。这与大多数其他正则表达式库不同,其中“快速匹配测试”方法在字符串中任何位置匹配正则表达式时返回 true。如果 myString 为 abc,则 myString.matches("bc") 返回 false。 bc 匹配 abc,但 ^bc$(实际在此处使用)不匹配。

myString.replaceAll("regex", "replacement") 使用您指定的替换字符串替换字符串中所有正则表达式匹配项。这并不奇怪。与正则表达式匹配的所有字符串部分都将被替换。您可以在替换文本中通过 $1、$2、$3 等使用捕获括号的内容。$0(零美元)插入整个正则表达式匹配项。如果存在第 12 个反向引用,则 $12 将替换为它,或者如果反向引用少于 12 个,则替换为第 1 个反向引用后跟文字“2”。如果存在 12 个或更多反向引用,则无法在替换文本中插入紧跟文字“2”的第一个反向引用。

在替换文本中,美元符号后不跟数字会导致抛出 IllegalArgumentException。如果反向引用少于 9 个,则美元符号后跟大于反向引用数量的数字会抛出 IndexOutOfBoundsException。因此,如果替换字符串是用户指定的字符串,请小心。要将美元符号插入为文字,请在替换文本中使用 \$。在源代码中将替换文本编码为文字字符串时,请记住反斜杠本身也必须进行转义:"\\$"

myString.split("regex") 在每个正则表达式匹配处拆分字符串。该方法返回一个字符串数组,其中每个元素都是两个正则表达式匹配项之间的原始字符串的一部分。匹配项本身不包含在数组中。使用 myString.split("regex", n) 获取一个最多包含 n 个项目的数组。结果是字符串最多拆分 n-1 次。字符串中的最后一个项目是原始字符串未拆分的剩余部分。

使用模式类

在 Java 中,可以使用 Pattern.compile() 类工厂编译正则表达式。此工厂返回类型为 Pattern 的对象。例如:Pattern myPattern = Pattern.compile("regex"); 您可以将某些选项指定为可选的第二个参数。 Pattern.compile("regex", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE) 使正则表达式对美国 ASCII 字符不区分大小写,使 匹配换行符,并使 字符串锚定开始和结束 也匹配嵌入式换行符。使用 Unicode 字符串时,如果您想让正则表达式对所有语言中的所有字符不区分大小写,请指定 Pattern.UNICODE_CASE。除非您确定字符串仅包含美国 ASCII 字符并且想要提高性能,否则您应始终指定 Pattern.CANON_EQ 以忽略 Unicode 编码中的差异。

如果您将在源代码中经常使用相同的正则表达式,则应创建一个 Pattern 对象以提高性能。创建 Pattern 对象还允许您将匹配选项作为第二个参数传递给 Pattern.compile() 类工厂。如果您使用上述 String 方法之一,则指定选项的唯一方法是将模式修改器嵌入到正则表达式中。在正则表达式的开头放置 (?i) 会使其不区分大小写。 (?m) 等效于 Pattern.MULTILINE(?s) 等于 Pattern.DOTALL(?u)Pattern.UNICODE_CASE 相同。遗憾的是,Pattern.CANON_EQ 没有等效的嵌入式模式修改器。

使用 myPattern.split("subject") 用已编译的正则表达式拆分 subject 字符串。此调用与 myString.split("regex") 的结果完全相同。不同之处在于,前者更快,因为正则表达式已经编译过了。

使用 Matcher 类

除了拆分字符串(参见上一段),您还需要从 Pattern 对象创建一个 Matcher 对象。 Matcher 将执行实际工作。拥有两个单独类的优势在于,您可以从单个 Pattern 对象创建许多 Matcher 对象,从而同时将正则表达式应用于许多 subject 字符串。

要创建一个 Matcher 对象,只需像这样调用 Pattern.matcher()myMatcher = Pattern.matcher("subject")。如果您已经从同一模式创建了 Matcher 对象,请调用 myMatcher.reset("newsubject"),而不是创建新的匹配器对象,以减少垃圾并提高性能。无论哪种方式,myMatcher 现在都已准备就绪。

要查找正则表达式在 subject 字符串中的第一个匹配项,请调用 myMatcher.find()。要查找下一个匹配项,请再次调用 myMatcher.find()。当 myMatcher.find() 返回 false,表示没有更多匹配项时,下一次调用 myMatcher.find() 将再次找到第一个匹配项。当 find() 失败时,Matcher 会自动重置为字符串的开头。

Matcher 对象保存上次匹配的结果。调用其方法 start()end()group() 以获取有关整个正则表达式匹配以及 捕获括号 之间匹配的详细信息。这些方法中的每一个都接受一个表示 反向引用 编号的单个 int 参数。省略参数以获取有关整个正则表达式匹配的信息。 start() 是匹配中第一个字符的索引。 end() 是匹配后第一个字符的索引。两者都相对于 subject 字符串的开头。因此,匹配的长度为 end() - start()group() 返回由正则表达式或一对捕获括号匹配的字符串。

myMatcher.replaceAll("replacement")myString.replaceAll("regex", "replacement") 的结果完全相同。同样,区别在于速度。

通过 Matcher 类,您可以在自己的代码中执行搜索和替换,并计算每个正则表达式匹配项的替换文本。您可以使用 appendReplacement()appendTail() 来执行此操作。具体方法如下

StringBuffer myStringBuffer = new StringBuffer();
myMatcher = myPattern.matcher("subject");
while (myMatcher.find()) {
  if (checkIfThisMatchShouldBeReplaced()) {
    myMatcher.appendReplacement(myStringBuffer, computeReplacementString());
  }
}
myMatcher.appendTail(myStringBuffer);

显然,checkIfThisMatchShouldBeReplaced()computeReplacementString() 是您提供的方法的占位符。第一个返回 true 或 false,表示是否应进行替换。请注意,跳过替换比用与匹配项完全相同的文本替换匹配项要快得多。computeReplacementString() 返回实际的替换字符串。

正则表达式、文字字符串和反斜杠

在 Java 文字字符串中,反斜杠是一个转义字符。文字字符串 "\\" 是一个单反斜杠。在正则表达式中,反斜杠也是一个转义字符。正则表达式 \\ 匹配一个单反斜杠。此正则表达式作为 Java 字符串时,变为 "\\\\"。没错:4 个反斜杠匹配一个反斜杠。

正则表达式 \w 匹配一个单词字符。作为 Java 字符串,它写为 "\\w"

在 Java 代码中为 String.replaceAll() 等方法提供替换字符串作为 Java 文字字符串时,也会出现相同的反斜杠混乱情况。在替换文本中,当您想用实际的美元符号或反斜杠替换正则表达式匹配项时,必须将美元符号编码为 \$,将反斜杠编码为 \\。但是,反斜杠也必须在 Java 文字字符串中转义。因此,替换文本中的一个单美元符号在写为 Java 文字字符串时变为 "\\$"。单反斜杠变为 "\\\\"。没错:4 个反斜杠插入一个反斜杠。

进一步阅读

Java 正则表达式 - 驯服 java.util.regex 引擎如果您想更详细地了解 java.util.regex 包提供的所有功能,您可能想获取 Mehran Habibi 撰写、Apress 出版的“Java 正则表达式”一书。虽然本网站上的 正则表达式教程 更完整、更详细,但 Habibi 先生的书包含了一个节奏较慢的正则表达式教程。这本书肯定提供了比此网页更多的 java.util.regex 包信息和示例。

我的 Java 正则表达式书籍评论

| 快速入门 | 教程 | 工具和语言 | 示例 | 参考 | 书籍评论 |

| grep | PowerGREP | RegexBuddy | RegexMagic |

| EditPad Lite | EditPad Pro |

| Boost | Delphi | GNU (Linux) | Groovy | Java | JavaScript | .NET | PCRE (C/C++) | PCRE2 (C/C++) | Perl | PHP | POSIX | PowerShell | Python | R | Ruby | std::regex | Tcl | VBScript | Visual Basic 6 | wxWidgets | XML Schema | Xojo | XQuery & XPath | XRegExp |

| MySQL | Oracle | PostgreSQL |