13.9 Pattern类的方法
到目前为止,我们只使用测试示例创建了Pattern对象的最基本形式。这一小节介绍高级技术,比如创建带有标志的模式和使用嵌入标志表达式。并且介绍我们还没有讨论过的其他一些有用的方法。
13.9.1 创建带有标志的模式
Pattern类定义了另一个compile方法,它接受一组影响匹配模式的方式的标志。标志参数是一个位掩码,它可能包括以下任何公共静态字段:
l Pattern.CANON_EQ——启用规范相等性。如果指定了这个标志,当(并且仅当)两个字符的完整规范分解匹配时,才认为它们匹配。例如,当指定了这个标志时,表达式“a\u030A”和字符串“\u00E5”匹配。默认情况下,匹配不考虑规范相等性。指定这个标志可能会导致性能的降低。
l Pattern.CASE_INSENSITIVE——启用不区分大小写的匹配。默认情况下,不区分大小写的匹配假定只匹配US-ASCII字符集中的字符。通过同时指定UNICODE_CASE和这个标志,可以启用识别Unicode的不区分大小写匹配。也可以通过嵌入标志表达式(? i)启用不区分大小写匹配。指定这个标志可能导致轻微的性能降低。
l Pattern.COMMENTS——允许在模式中使用空白和注释。在这种模式下,空白被忽略,并且嵌入的注释(#开始,直到行末尾)被忽略。也可以通过嵌入标志表达式(? x)启用注释模式。
l Pattern.DOTALL——启用dotall模式。在dotall模式下,表达式.匹配任何字符,包括行终止符。默认情况下,这个表达式不匹配行终止符。也可以通过嵌入标志表达式(? s)启用dotall模式。(表达式中的s是“单行”模式的助记符,在Perl中把这种模式称为单行模式。)
l Pattern.LITERAL——启用模式的字面量解析。指定了这个标志时,指定模式的输入字符串被当作字面量字符的序列。输入序列中的元字符或者转移序列没有特殊含义。和这个标志结合使用时,标志CASE_INSENSITIVE和UNICODE_CASE保留它们对匹配的影响。其他标志则变成多余的。没有用于启用字面量解析的嵌入标志字符。
l Pattern.MULTILINE——启用多行模式。在多行模式下,表达式^和$分别正好在行终止符或者输入序列的末尾的之前或者之后。默认情况下,这些表达式只匹配整个输入序列的开头和结尾。也可以通过嵌入标志表达式(? m)启动多行模式。
l Pattern.UNICODE_CASE——启用识别Unicode的大小写折叠。指定了这个标志时,不区分大小写的匹配(由CASE_INSENSITIVE标志启动)按照和Unicode标准一致的方式完成。默认情况下,不区分大小写的匹配假定只匹配US-ASCII字符集中的字符。也可以通过嵌入标志表达式(? u)启用识别Unicode的大小写折叠。指定这个标志可能导致性能降低。
l Pattern.UNIX_LINES——启用UNIX行模式。在这种模式下,在.、^和$的行为中只把‘\n’识别为行终止符。也可以使用嵌入标志表达式(?d)启动UNIX行模式。
下面我们将修改测试示例RegexTestHarness.java,使用区分大小写的匹配创建模式。
首先,修改代码调用compile的替代版本:
Pattern pattern =
Pattern.compile(console.readLine("%nEnter your regex: "),
Pattern.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”和两次出现匹配,而不管大小写如何。为了编译带有多个标志的模式,需要使用位或操作符“|”分隔要包含的标志。为了表达明确,下面的代码示例硬编码正则表达式,而没有从控制台读取:
pattern = Pattern.compile("[az]$",
Pattern.MULTILINE | Pattern.UNIX_LINES);
你也可以指定一个int变量:
final int flags =
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
Pattern pattern = Pattern.compile("aa", flags);
13.9.2 嵌入标志表达式
可以使用嵌入标志表达式(embedded flag expression)启用各种标志。嵌入标志表达式是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的公共可访问字段对应的嵌入标志表达式如表13-5所示。
表13-5 嵌入标志表达式
|
常 量 |
等效的嵌入标志表达式 |
|
Pattern.CANON_EQ |
无 |
|
Pattern.CASE_INSENSITIVE |
(?i) |
|
Pattern.COMMENTS |
(?x) |
|
Pattern.MULTILINE |
(?m) |
|
Pattern.DOTALL |
(?s) |
|
Pattern.LITERAL |
无 |
|
Pattern.UNICODE_CASE |
(?u) |
|
Pattern.UNIX_LINES |
(?d) |
13.9.3 使用matches(String,CharSequence)方法
Pattern类定义了一个方便的matches方法,它允许你快速地检查模式是否出现在给定的输入字符串中。和所有公共静态方法一样,通过其类名称调用matches,比如Pattern. matches("\\d","1");。在这个例子中,方法返回true,因为数字“1”匹配正则表达式\d。
13.9.4 使用split(String)方法
split方法是用于从进行匹配操作的模式的任何一侧收集文本的非常有用的工具。比如在下面的SplitDemo.java中,split方法可以从字符串“one:two:three:four:five”中提取单词“one two three four five”:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
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 = Pattern.compile(REGEX);
String[] items = p.split(INPUT);
for(String s : items) {
System.out.println(s);
}
}
}
输出如下:
one
two
three
four
five
为了简单起见,我们匹配一个字符串字面量,冒号(:),没有使用复杂的正则表达式。因为我们仍然使用Pattern和Matcher对象,所以你可以使用split方法获得任何正则表达式的任何一侧的文本。下面是个相同的例子SplitDemo2.java,它被修改为在数字处进行拆分:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class SplitDemo2 {
private static final String REGEX = "\\d";
private static final String INPUT
= "one9two4three7four1five";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
String[] items = p.split(INPUT)
for(String s : items) {
System.out.println(s);
}
}
}
输出如下:
one
two
three
four
five
13.9.5 其他工具方法
你会发现下面的方法也有一些用处:
l public static String quote(String s)——返回指定的String的字面量模式String。这个方法生成的String可以用于创建匹配s的Pattern,就像它是字面量模式一样。不会赋予输入序列中的元字符或者转移序列特殊的含义。
l public String toString()——返回这个模式的String表示。这是被编译的这个模式的正则表达式。
13.9.6 java.lang.String中和Pattren等同的方法
java.lang.String也通过若干方法支持正则表达式,这些方法模拟java.util.regex. Pattern的行为。为了便于参考,下面列出它们API中的关键摘要:
l public boolean matches(String regex)——判断这个字符串是否匹配给定的正则表达式。调用这个方法的str.matches(regex)形式产生的结果和表达式Pattern. matches(regex, str)完全一样。
l public String[] split(String regex, int limit)——按照给定正则表达式的匹配拆分这个字符串。调用这个方法的str.split(regex, n)产生的结果和表达式Pattern.compile (regex).split(str, n)完全一样。
l public String[] split(String regex)——按照给定正则表达式的匹配拆分这个字符串。这个方法的结果与使用给定表达式和限制实参0调用两个实参的拆分方法相同。结果数组内不包括末尾的空白字符串。
还有一个替换方法,它使用另一个CharSequence替换CharSequence:
l public String replace(CharSequence target, CharSequence replacement)——使用指定的字面量替换序列,替换这个字符串中和字面量目标序列匹配的每个子字符串。从字符串的开始到末尾进行替换操作,例如,使用“b”替换字符串“aaa”中的“aa”,结果为“ba”,而不是“ab”。






