Pattern 类的方法

到目前为止,我们仅使用测试工具以最基本的形式创建Pattern对象。本节探讨了高级技术,例如使用标志创建 Pattern 以及使用嵌入式标志表达式。它还探讨了一些我们尚未讨论的其他有用方法。

创建带有标志的图案

Pattern类定义了备用compile方法,该方法接受一组影响 Pattern 匹配方式的标志。 flags 参数是一个位掩码,可以包括以下任何公共静态字段:

  • Pattern.CANON_EQ启用规范对等。当指定此标志时,只有且仅当其完全规范分解匹配时,两个字符才会被视为匹配。例如,指定此标志时,表达式"a\u030A"将与字符串"\u00E5"匹配。默认情况下,匹配不考虑规范对等。指定此标志可能会导致性能下降。

  • Pattern.CASE_INSENSITIVE启用不区分大小写的匹配。默认情况下,不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。可以通过将 UNICODE_CASE 标志与该标志一起指定来启用 Unicode 感知的不区分大小写的匹配。还可以通过嵌入的标志表达式(?i)启用不区分大小写的匹配。指定此标志可能会导致轻微的性能损失。

  • Pattern.COMMENTS允许在 Pattern 中包含空格和 注解。在这种 Pattern 下,空格将被忽略,并且以#开头的嵌入 注解 将被忽略,直到行尾为止。也可以通过嵌入式标志表达式(?x)启用 注解Pattern。

  • Pattern.DOTALL启用 dotallPattern。在 dotallPattern 下,表达式.匹配任何字符,包括行终止符。默认情况下,此表达式与行终止符不匹配。还可以通过嵌入式标志表达式(?s)启用 DotallPattern。 (s 是“单行”Pattern 的助记符,在 Perl 中被称为.)

  • Pattern.LITERAL启用 Pattern 的 Literals 分析。指定此标志后,将指定 Pattern 的 Importing 字符串 视为 Literals 字符序列。Importing 序列中的元字符或转义序列将没有特殊含义。与此标志结合使用时,标志CASE_INSENSITIVEUNICODE_CASE保留对匹配的影响。其他标志变得多余。没有用于启用 Literals 分析的嵌入式标志字符。

  • Pattern.MULTILINE启用多行 Pattern。在多行 Pattern 下,表达式^$分别在行终止符或 Importing 序列的结尾之后或之前匹配。默认情况下,这些表达式仅在整个 Importing 序列的开头和结尾匹配。也可以通过嵌入式标志表达式(?m)启用多行 Pattern。

  • Pattern.UNICODE_CASE启用支持 Unicode 的大小写折叠。指定此标志后,以CASE_INSENSITIVE标志启用时,不区分大小写的匹配将以与 Unicode 标准一致的方式进行。默认情况下,不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。还可以通过嵌入的标志表达式(?u)启用支持 Unicode 的大小写折叠。指定此标志可能会导致性能下降。

  • Pattern.UNIX_LINES启用 UNIX 行 Pattern。在此 Pattern 下,在.^$的行为中仅识别'\n'行终止符。也可以通过嵌入式标志表达式(?d)启用 UNIX 行 Pattern。

在以下步骤中,我们将修改测试工具RegexTestHarness.java以创建不区分大小写的匹配 Pattern。

首先,修改代码以调用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.

如您所见,字符串Literals“ dog”无论大小写都匹配这两种情况。要编译具有多个标志的 Pattern,请使用按位或运算符“ |”分隔要包含的标志。为了清楚起见,以下代码示例对正则表达式进行硬编码,而不是从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);

嵌入式标志表达式

也可以使用嵌入式标志表达式来启用各种标志。嵌入式标志表达式是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.

再一次,无论大小写,所有 match 都会成功。

下表显示了与Pattern的公共可访问字段相对应的嵌入式标志表达式:

Constant等效嵌入式标志表达
Pattern.CANON_EQNone
Pattern.CASE_INSENSITIVE(?i)
Pattern.COMMENTS(?x)
Pattern.MULTILINE(?m)
Pattern.DOTALL(?s)
Pattern.LITERALNone
Pattern.UNICODE_CASE(?u)
Pattern.UNIX_LINES(?d)

使用 matchs(String,CharSequence)方法

Pattern类定义了一种方便的matches方法,该方法使您可以快速检查给定 Importing 字符串 中是否存在 Pattern。与所有公共静态方法一样,您应通过matches的类名来调用它,例如Pattern.matches("\\d","1");。在此示例中,该方法返回true,因为数字“ 1”与正则表达式\d匹配。

使用 split(String)方法

split方法是一个很棒的工具,用于收集位于匹配 Pattern 两侧的文本。如下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

为简单起见,我们匹配了字符串Literals 冒号(:)而不是复杂的正则表达式。由于我们仍在使用PatternMatcher对象,因此可以使用 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

其他 Util 方法

您可能会发现以下方法也很有用:

  • 公共静态字符串 引用(String s)返回指定String的 LiteralsPatternString。此方法产生一个String,可用来创建一个与String s匹配的Pattern,就好像它是 LiteralsPattern 一样。Importing 序列中的元字符或转义序列将没有特殊含义。

  • 公共字符串toString()返回此 Pattern 的String表示形式。这是从中编译此 Pattern 的正则表达式。

java.lang.String 中的 Pattern 方法等效项

通过多种模仿java.util.regex.Pattern行为的方法,java.lang.String中也存在正则表达式支持。为方便起见,下面提供了其 API 的主要摘录。

  • 公共布尔匹配(字符串 正则表达式):告诉此字符串 是否与给定的正则表达式匹配。以str.matches(regex)形式调用此方法所产生的结果与表达式Pattern.matches(regex, str)完全相同。

  • public String [] split(字符串 正则表达式,整数限制):将字符串 拆分为给定正则表达式的匹配项。以str.split(regex, n)形式调用此方法所产生的结果与表达式Pattern.compile(regex).split(str, n)相同

  • public String [] split(String regex):将字符串 拆分为给定正则表达式的匹配项。此方法的工作原理与您使用给定表达式且限制参数为零调用两参数拆分方法的方式相同。尾随空字符串 不包括在结果数组中。

还有一种替换方法,可以用一个CharSequence替换另一个:

  • 公共字符串 替换(CharSequence 目标,CharSequence 替换):将字符串 中与 Literals 目标序列匹配的每个子字符串 替换为指定的 Literals 替换序列。替换从字符串 的开头到结尾进行,例如,用字符串“ aaa”中的“ b”替换“ aa”将得到“ ba”而不是“ ab”。