Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
到目前为止,我们只使用测试工具以最基本的形式创建 Pattern
对象。本节探讨高级技术,例如使用标志创建模式和使用嵌入式标志表达式。它还探讨了我们尚未讨论的一些其他有用的方法。
Pattern
类定义了一个备用 compile
方法,该方法接受一组影响模式匹配方式的标志。flags 参数是一个位掩码,可能包含以下任何公共静态字段:
Pattern.CANON_EQ
启用规范等效。当指定此标志时,当且仅当两个字符的完整规范化分解匹配时,才认为这两个字符匹配。例如,当指定此标志时,表达式 "a\u030A"
将匹配字符串 "\u00E5"
。默认情况下,匹配不会将规范等效考虑在内。指定此标志可能会导致性能下降。Pattern.CASE_INSENSITIVE
启用不区分大小写的匹配。默认情况下,不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。通过将 UNICODE_CASE 标志与此标志一起指定,可以启用 Unicode 感知的不区分大小写的匹配。也可以通过嵌入式标志表达式 (?i)
启用不区分大小写的匹配。指定此标志可能会略微降低性能。Pattern.COMMENTS
允许模式中的空格和注释。在此模式下,将忽略空格,并忽略以 #
开头的嵌入式注释,直到行结束。也可以通过嵌入式标志表达式 (?x)
启用注释模式。Pattern.DOTALL
启用 dotall 模式。在 dotall 模式下,表达式 .
匹配任何字符,包括行终止符。默认情况下,此表达式与行终止符不匹配。也可以通过嵌入式标志表达式 (?s)
启用 Dotall 模式。(s 是“单行”模式的助记符,在 Perl 中就是这样称呼的。)Pattern.LITERAL
启用模式的文字解析。指定此标志后,指定模式的输入字符串将被视为文字字符序列。输入序列中的元字符或转义序列将没有特殊含义。当与此标志一起使用时,标志 CASE_INSENSITIVE
和 UNICODE_CASE
会保持对匹配的影响。其他标志变得多余。没有用于启用文字解析的嵌入标志字符。Pattern.MULTILINE
启用多行模式。在多行模式下,表达式 ^
和 $
分别在行终止符之后或之前匹配,或者在输入序列的末尾之前匹配。默认情况下,这些表达式仅在整个输入序列的开头和结尾处匹配。也可以通过嵌入式标志表达式 (?m)
启用多行模式。Pattern.UNICODE_CASE
启用支持 Unicode 的大小写折叠。指定此标志后,当由 CASE_INSENSITIVE
标志启用时,不区分大小写的匹配将以与 Unicode 标准一致的方式完成。默认情况下,不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。也可以通过嵌入式标志表达式 (?u)
启用支持 Unicode 的大小写折叠。指定此标志可能会导致性能下降。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”都匹配这两种情况。要编译带有多个标志的模式,请使用按位或运算符 "|
" 分隔要包含的标志。为清楚起见,以下代码示例对正则表达式进行硬编码,而不是从 Console
中读取它:
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);
也可以使用 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 |
(?i) |
Pattern.COMMENTS |
(?x) |
Pattern.MULTILINE |
(?m) |
Pattern.DOTALL |
(?s) |
Pattern.LITERAL |
无 |
Pattern.UNICODE_CASE |
(?u) |
Pattern.UNIX_LINES |
(?d) |
matches(String,CharSequence)
方法Pattern
类定义了一个方便的 matches
方法,该方法允许你快速检查给定输入字符串中是否存在模式。与所有公共静态方法一样,你应该通过其类名调用 matches
,例如 Pattern.matches("\\d","1");
。在此示例中,该方法返回 true
,因为数字“1”与正则表达式 \d
匹配。
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); } } }
OUTPUT: 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); } } }
OUTPUT: one two three four five
你可能会发现以下方法也有一些用处:
public static String quote(String s)
返回指定 String
的文字模式 String
。此方法生成 String
,可用于创建与 String s
匹配的 Pattern
,就像它是文字模式一样。输入序列中的元字符或转义序列将没有特殊含义。public String toString()
返回此模式的 String
表示形式。这是编译此模式的正则表达式。java.lang.String
中的模式方法等价物java.lang.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)
形式的此方法会产生与表达式 Pattern.compile(regex).split(str, n)
相同的结果。public String[] split(String regex)
:围绕给定正则表达式的匹配拆分此字符串。此方法与调用具有给定表达式且 limit 参数为零的双参数 split 方法的方法相同。结果数组中不包括尾随空字符串。还有一个替换方法,用另一个 CharSequence
替换一个:
public String replace(CharSequence target,CharSequence replacement)
:将此字符串中与 target 匹配的每个子字符串替换为指定的 replacement 序列。替换从字符串的开头到结尾,例如,在字符串“aaa”中将“aa”替换为“b”将导致“ba”而不是“ab”。