# 模式类的方法

> 原文： [https://docs.oracle.com/javase/tutorial/essential/regex/pattern.html](https://docs.oracle.com/javase/tutorial/essential/regex/pattern.html)

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

## 使用标志创建模式

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

*   [`Pattern.CANON_EQ`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#CANON_EQ) 启用规范等效。指定此标志时，如果且仅当它们的完整规范分解匹配时，将认为两个字符匹配。例如，当指定此标志时，表达式`"a\u030A"`将匹配字符串`"\u00E5"`。默认情况下，匹配不会将规范等效考虑在内。指定此标志可能会导致性能下降。
*   [`Pattern.CASE_INSENSITIVE`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#CASE_INSENSITIVE) 启用不区分大小写的匹配。默认情况下，不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。通过将 UNICODE_CASE 标志与此标志一起指定，可以启用 Unicode 感知的不区分大小写的匹配。也可以通过嵌入式标志表达式`(?i)`启用不区分大小写的匹配。指定此标志可能会略微降低性能。
*   [`Pattern.COMMENTS`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#COMMENTS) 允许模式中的空格和注释。在此模式下，将忽略空格，并忽略以`#`开头的嵌入式注释，直到行结束。注释模式也可以通过嵌入的标志表达式`(?x)`启用。
*   [`Pattern.DOTALL`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#DOTALL) 启用 dotall 模式。在 dotall 模式下，表达式`.`匹配任何字符，包括行终止符。默认情况下，此表达式与行终止符不匹配。也可以通过嵌入式标志表达式`(?s)`启用 Dotall 模式。 （s 是“单行”模式的助记符，这是在 Perl 中调用的。）
*   [`Pattern.LITERAL`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#LITERAL) 启用模式的文字解析。指定此标志后，指定模式的输入字符串将被视为文字字符序列。输入序列中的元字符或转义序列将没有特殊含义。当与该标志一起使用时，标志`CASE_INSENSITIVE`和`UNICODE_CASE`保持对匹配的影响。其他标志变得多余。没有用于启用文字解析的嵌入标志字符。
*   [`Pattern.MULTILINE`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#MULTILINE) 启用多线模式。在多行模式中，表达式`^`和`$`分别在行终止符之后或之前匹配，或者在输入序列的末尾之前匹配。默认情况下，这些表达式仅在整个输入序列的开头和结尾处匹配。也可以通过嵌入式标志表达式`(?m)`启用多行模式。
*   [`Pattern.UNICODE_CASE`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#UNICODE_CASE) 启用 Unicode 识别的案例折叠。指定此标志时，由`CASE_INSENSITIVE`标志启用时，不区分大小写的匹配将以与 Unicode 标准一致的方式完成。默认情况下，不区分大小写的匹配假定只匹配 US-ASCII 字符集中的字符。也可以通过嵌入式标志表达式`(?u)`启用支持 Unicode 的案例折叠。指定此标志可能会导致性能下降。
*   [`Pattern.UNIX_LINES`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#UNIX_LINES) 启用 UNIX 线路模式。在此模式下，`.`，`^`和`$`的行为中仅识别`'\n'`行终止符。也可以通过嵌入式标志表达式`(?d)`启用 UNIX 行模式。

在以下步骤中，我们将修改测试工具 [`RegexTestHarness.java`](examples/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”匹配两种情况，无论情况如何。要编译具有多个标志的模式，请使用按位 OR 运算符“`|`”分隔要包含的标志。为清楚起见，以下代码示例对正则表达式进行硬编码，而不是从`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`](examples/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`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#matches-java.lang.String-java.lang.CharSequence-) 方法，允许您快速检查给定输入字符串中是否存在模式。与所有公共静态方法一样，您应该通过其类名调用`matches`，例如`Pattern.matches("\\d","1");`。在此示例中，该方法返回`true`，因为数字“1”与正则表达式`\d`匹配。

## 使用`split(String)`方法

[`split`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#split-java.lang.CharSequence-) 方法是一个很好的工具，用于收集位于匹配模式两侧的文本。如下 [`SplitDemo.java`](examples/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`](examples/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)`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#quote-java.lang.String-) 返回指定`String`的文字模式`String`。此方法生成`String`，可用于创建与`String s`匹配的`Pattern`，就像它是文字模式一样。输入序列中的元字符或转义序列将没有特殊含义。
*   [`public String toString()`](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#toString--) 返回此模式的`String`表示。这是编译此模式的正则表达式。

## `java.lang.String`中的模式方法等价

通过几种模拟`java.util.regex.Pattern`行为的方法，`java.lang.String`中也存在正则表达式支持。为方便起见，下面介绍了 API 的主要摘录。

*   [`public boolean matches(String regex)`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#matches-java.lang.String-) ：判断此字符串是否与给定的正则表达式匹配。 `_str_ 。匹配（_ 正则表达式 _）`形式的这种方法的调用产生与表达式 `Pattern.matches（_ 完全相同的结果。正则表达 _， _str_ ）`。
*   [`public String[] split(String regex, int limit)`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int-) ：围绕给定正则表达式的匹配拆分此字符串。 `_str_ .split（ _regex_ ， _n_ ）`形式的这种方法的调用产生与表达`相同的结果。 Pattern.compile（_ 正则表达式 _）。split（ _str_ ， _n_ ）`
*   [`public String[] split(String regex)`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-) ：围绕给定正则表达式的匹配拆分此字符串。此方法与调用具有给定表达式且 limit 参数为零的双参数 split 方法的方法相同。结果数组中不包括尾随空字符串。

还有一种替换方法，用一个`CharSequence`替换另一个`CharSequence`：

*   [`public String replace(CharSequence target,CharSequence replacement)`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replace-java.lang.CharSequence-java.lang.CharSequence-) ：将与该文字目标序列匹配的该字符串的每个子字符串替换为指定的文字替换序列。替换从字符串的开头到结尾，例如，在字符串“aaa”中将“aa”替换为“b”将导致“ba”而不是“ab”。