在继续下一节之前,确认开发环境支持必需的包,并保存和编译这段代码。 【译者注】
由于当前版本的 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 环境也采用该用具。
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027
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(\
Pattern pattern = Pattern.compile(scanner.nextLine()); System.out.printf(\ Matcher matcher = pattern.matcher(scanner.nextLine()); boolean found = false; while (matcher.find()) { System.out.printf(
\found the text \\\starting at index %d and ending at index %d.%n\
matcher.group(), matcher.start(), matcher.end()
);
found = true; }
if (!found) {
System.out.printf(\ } } } }
JDK 1.4 适用的测试用具(RegexTestHarnessV4.java):
001 002 003 004 005 006 007 008 009 010 011 012 013
014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032
import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException;
import java.io.InputStreamReader; 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(\
Pattern pattern = Pattern.compile(br.readLine()); System.out.print(\ Matcher matcher = pattern.matcher(br.readLine()); boolean found = false; while (matcher.find()) {
System.out.println(\matcher.group() +
\ \ \ found = true; }
if (!found) {
System.out.println(\ } } } }
2 字符串返回目录
在大多数的情况下,API所支持模式匹配的基本形式是匹配字符串,如果正则表达式是foo,输入的字符串也是 foo,这个匹配将会是成功的,因为这两个字符串是相同的。试着用测试用具来测试一下:
Enter your regex: foo
Enter input string to search: foo
I found the text \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 search: foofoofoo
I found the text \starting at index 0 and ending at index 3.
I found the text \starting at index 3 and ending at index 6.
I found the text \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 \starting at index 0 and ending at index 4.
虽然在输入的字符串中没有点(.),但这个匹配仍然是成功的。这是由于点(.)是一个元字符(metacharacters)(被这个匹配翻译成了具有特殊意义的字符了)。这个例子为什么能匹配成功的原因在于,元字符.指的是“任意字符”。
API 所支持的元字符有:([{\\^-$|}])?*+.
注意:在学习过更多的如何构建正则表达式后,你会碰到这些情况:上面的这些特殊字符不应该被处理为元字符。然而也能够使用这个清单来检查一个特殊的字符是否会被认为是元字符。例如,字符 !、@ 和 # 决不会有特殊的意义。
有两种方法可以强制将元字符处理成为普通字符: 1. 在元字符前加上反斜线(\\);
2. 把它放在\\Q(引用开始)和\\E(引用结束)之间[5]。在使用这种技术时,\\Q和\\E能被放于表达式中的任何位置(假设先出现\\Q)
[6]
3 字符类返回目录
如果你曾看过 Pattern 类的说明,会看到一些构建正则表达式的概述。在这一节中你会发现下面的一些表达式:
字符类
a, b 或 c(简单类) [abc]
除 a, b 或 c 之外的任意字符(取反) [^abc]
a 到 z,或 A 到 Z,包括(范围) [a-zA-Z]
[a-d[m-p]] a 到 d,或 m 到 p:[a-dm-p](并集) [a-z&&[def]] d,e 或 f(交集)
[a-z&&[^bc]] 除 b 和 c 之外的 a 到 z 字符:[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 \starting at index 0 and ending at index 3.
Enter your regex: [bcr]at
Enter input string to search: cat
I found the text \starting at index 0 and ending at index 3.
Enter your regex: [bcr]at
Enter input string to search: rat
I found the text \starting at index 0 and ending at index 3.