1. 概要

Javaで正規表現を使用する場合、これらのシーケンスに存在する メタ文字を処理せずに、リテラル形式で正規表現パターンを一致させる必要がある場合があります。

このクイックチュートリアルでは、手動とJavaが提供する Pattern.quote()メソッドを使用して、正規表現内のメタ文字をエスケープする方法を見てみましょう。

2. メタ文字をエスケープせずに

金額のリストを保持する文字列について考えてみましょう。

String dollarAmounts = "$100.25, $100.50, $150.50, $100.50, $100.75";

ここで、その中の特定の金額の発生を検索する必要があると想像してみましょう。 それに応じて正規表現パターン文字列を初期化しましょう。

String patternStr = "$100.50";

まず、メタ文字をエスケープせずに正規表現検索を実行するとどうなるかを調べてみましょう

public void whenMetacharactersNotEscaped_thenNoMatchesFound() {
    Pattern pattern = Pattern.compile(patternStr);
    Matcher matcher = pattern.matcher(dollarAmounts);

    int matches = 0;
    while (matcher.find()) {
        matches++;
    }

    assertEquals(0, matches);
}

ご覧のとおり、 matcherは、dollarAmounts文字列内で$150.50が1回でも検出されません。 これは単に、ドル記号で始まる patternStrが原因です。これは、行の終わりを指定する正規表現メタ文字です。

ご想像のとおり、すべての正規表現メタ文字で同じ問題が発生します。 「5^ 3 」のような指数のキャレット(^)を含む数式や、「 users \ bob [」のような円記号(\)を使用するテキストを検索することはできません。 X169X]」。

3. メタ文字を手動で無視する

次に、検索を実行する前に、正規表現内のメタ文字をエスケープしましょう。

public void whenMetacharactersManuallyEscaped_thenMatchingSuccessful() {
    String metaEscapedPatternStr = "\\Q" + patternStr + "\\E";
    Pattern pattern = Pattern.compile(metaEscapedPatternStr);
    Matcher matcher = pattern.matcher(dollarAmounts);

    int matches = 0;
    while (matcher.find()) {
        matches++;
    }

    assertEquals(2, matches);
}

今回は、検索に成功しました。 しかし、これはいくつかの理由から理想的な解決策にはなり得ません。

  • 文字列連結は、コードの追跡をより困難にするメタ文字をエスケープするときに実行されます。
  • ハードコードされた値が追加されたため、クリーンコードが少なくなりました

4. Pattern.quote()を使用します

最後に、正規表現のメタ文字を無視する最も簡単でクリーンな方法を見てみましょう。

Javaは、Patternクラス内に quote()メソッドを提供して、文字列のリテラルパターンを取得します。

public void whenMetacharactersEscapedUsingPatternQuote_thenMatchingSuccessful() {
    String literalPatternStr = Pattern.quote(patternStr);
    Pattern pattern = Pattern.compile(literalPatternStr);
    Matcher matcher = pattern.matcher(dollarAmounts);

    int matches = 0;
    while (matcher.find()) {
        matches++;
    }

    assertEquals(2, matches);
}

5. 結論

この記事では、正規表現パターンをリテラル形式で処理する方法について説明しました。

正規表現メタ文字をエスケープしないと期待どおりの結果が得られなかったこと、および正規表現パターン内のメタ文字をエスケープする方法を手動で Pattern.quote()メソッドを使用して実行できることを確認しました。

ここで使用されているすべてのコードサンプルの完全なソースコードは、GitHubにあります。