集册 Java 精简入门教程 Java 正则表达式

Java 正则表达式

欢马劈雪     最近更新时间:2020-08-21 11:09:41

624

正则表达式 基本来讲是一种模式,描述一组具有该共同模式的字符串。如果您是 Perl 程序员,应该非常熟悉 Java 语言中的正则表达式 (regex) 模式语法。但是,如果您不习惯使用正则表达式语法,它可能看起来很怪异。本节指导您在 Java 程序中使用正则表达式。

Regular Expressions API

下面是一组具有某些共性的字符串:

  • A string
  • A longer string
  • A much longer string

注意,这些字符串中的每一个都以 a 开头,以 string 结尾。Java Regular Expressions API 可帮助您将这些元素提取出来,查看它们之间的模式,然后使用已收集的信息做有趣的工作。

Regular Expressions API 有 3 个您几乎总是在使用的核心类:

  • Pattern 描述一种字符串模式。
  • Matcher 测试一个字符串,查看它是否与模式匹配。
  • PatternSyntaxException 告诉您,无法接受您尝试定义的模式的某个方面。

很快您就会开始使用简单的正则表达式模式,该模式使用了这些类。但是在这么做之前,看看 regex 模式语法。

regex 模式语法

regex 模式 描述字符串的结构,表达式会尝试在输入字符串中查找该结构。这是正则表达式可能看起来有点奇怪的地方。但是,一旦您理解了该语法,就可以更轻松地解释它。表 1 列出了在模式字符串中使用的一些最常见的 regex 构造:

表 1. 常见 regex 构造
Regex 构造符合匹配条件的内容
.任何字符
?前面的零 (0) 或一 (1) 个字符或数字
*前面的零 (0) 或更多个字符或数字
+前面的一 (1) 或更多个字符或数字
[]一个字符或数字范围
^后面的条件的否定(即”非 后面的条件 ”)
\d任何数字(也可表示为 [0-9]
\D任何非数字(也可表示为 [^0-9]
\s任何空格字符(也可表示为 [\n\t\f\r]
\S任何非空格字符(也可表示为 [^\n\t\f\r]
\w任何单词字符(也可表示为 [a-zA-Z_0-9]
\W任何非单词字符(也可表示为 [^\w]

前几种构造称为 量词 ,因为它们对之前的内容进行量化。\d 等构造是预定义的字符类。任何在一种模式中没有特殊含义的字符都是文字并与自身匹配。

模式匹配

掌握 表 1 中的模式语法后,就能理解清单 1 中的简单示例了,这个示例使用了 Java Regular Expressions API 中的类。

清单 1. 使用 regex 进行模式匹配
Pattern pattern = Pattern.compile("a.*string");
  Matcher matcher = pattern.matcher("a string");
  boolean didMatch = matcher.matches();
  Logger.getAnonymousLogger().info (didMatch);
  int patternStartIndex = matcher.start();
  Logger.getAnonymousLogger().info (patternStartIndex);
  int patternEndIndex = matcher.end();
  Logger.getAnonymousLogger().info (patternEndIndex);

首先,清单 1 调用 compile()Pattern 上的一个静态方法)来创建一个 Pattern 类,并使用一个字符串文字来表示想要匹配的模式。该文字使用了 regex 模式语法。在本例中,该模式的中文翻译为:

_找到一个具有以下形式的字符串:Aa 后跟零或更多个字符,然后是 string

匹配方法

接下来,清单 1 在 Pattern 上调用 matcher()。该调用创建一个 Matcher 实例。 然后 Matcher 搜索您传入的字符串,寻找与您在创建 Pattern 时使用的模式字符串相匹配的结果。

每个 Java 语言字符串都是一个带索引的字符集合,索引从 0 开始,到字符串长度减 1 结束。Matcher 从 0 开始解析该字符串,寻找与它匹配的结果。处理完成后,Matcher 包含有关在输入字符串中找到(或未找到)匹配结果的信息。可在 Matcher 上调用各种方法来访问该信息:

  • matches() 告诉您整个输入序列是否与该模式准确匹配。
  • start() 告诉您匹配的字符串在输入字符串中开始处的索引值。
  • end() 告诉您匹配的字符串在输入字符串中结束处的索引值加 1 的结果。

清单 1 找到了一个从 0 开始,到 7 结束的匹配结果。因此,调用 matches() 会返回 true,调用 start() 会返回 0,调用 end() 会返回 8

lookingAt() 与 matches()

如果字符串中的元素比搜索模式中的字符要多,可使用 lookingAt() 代替 matches()lookingAt() 搜索与给定模式匹配的子字符串。例如,考虑下面这个字符串:

Here is a string with more than just the pattern.

您可在此字符串中搜索 a.*string,而且如果使用 lookingAt(),就会获得一个匹配结果。但是如果使用 matches(),就会返回 false,因为字符串中包含的内容比模式中的多。

regex 中的复杂模式

可使用 regex 类轻松完成简单的搜索,同时也可使用 Regular Expressions API 执行非常复杂的操作。

Wiki 几乎完全基于正则表达式。Wiki 内容基于用户的字符串输入,并且使用正则表达式来解析和格式化该输入。 任何用户都可输入一个 wiki 词组,从而在 wiki 中创建另一个主题的链接,这个词组通常是一系列串联的单词,每个单词以一个大写字母开头,类似这样:

MyWikiWord

假设一个用户输入下面这个字符串:

Here is a WikiWord followed by AnotherWikiWord, then YetAnotherWikiWord.

您可使用 regex 模式在这个字符串中搜索 wiki 单词,类似这样:

[A-Z][a-z]*([A-Z][a-z]*)+

下面是搜索 wiki 单词的代码:

String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
  Logger.getAnonymousLogger().info("Found this wiki word:" + matcher.group());
}

运行此代码,应在控制台中看到 3 个 wiki 单词。

替换字符串

搜索匹配内容很有用,但也可在找到匹配字符串后操作它们。您可将匹配的字符串替换为其他字符串,就像在文字处理程序中搜索一些文本并将它替换为其他文本一样。Matcher 有两个替换字符串元素的方法:

  • replaceAll() 将所有匹配值替换为一个指定的字符串。
  • replaceFirst() 仅将第一个匹配值替换为一个指定的字符串。

使用 Matcherreplace 方法很简单:

String input = "Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)+");
Matcher matcher = pattern.matcher(input);
Logger.getAnonymousLogger().info("Before:" + input);
String result = matcher.replaceAll("replacement");
Logger.getAnonymousLogger().info("After:" + result);

与之前一样,此代码会查找 wiki 单词。Matcher 找到一个匹配值时,它会将该 wiki 单词文本替换为相应的替换值。运行该代码时,可在控制台上看到以下消息:

Before:Here is WikiWord followed by AnotherWikiWord, then SomeWikiWord.
  After:Here is replacement followed by replacement, then replacement.

如果使用 replaceFirst(),则会看到此消息:

Before:Here is a WikiWord followed by AnotherWikiWord, then SomeWikiWord.
  After:Here is a replacement followed by AnotherWikiWord, then SomeWikiWord.

匹配和操作分组

搜索一个 regex 模式的匹配结果时,可获得有关找到的结果的信息。您已在 Matcherstart()end() 方法上看到过该功能。但也可以通过捕获 分组 来引用匹配值。

在每种模式中,通常通过将模式的各部分放在圆括号中来创建分组。分组从左向右编号,从 1 开始编号(分组 0 表示完整的匹配结果)。清单 2 中的代码将每个 wiki 单词替换为一个“包含”该单词的字符串:

清单 2. 匹配分组
展开阅读全文