web-dev-qa-db-ja.com

Java正規表現での特殊文字のエスケープ

Javaまたは、引用符ではなく)特殊文字(メタ文字)をエスケープして正規表現として使用するためのオープンソースライブラリにメソッドはありますか?

これは、個々の文字を手動でエスケープする必要なく、正規表現を動的に構築するのに非常に便利です。

たとえば、_\d+\.\d+_のような小数点を持つ数字に一致する_1.2_のような単純な正規表現と、次のコードを考えます。

_String digit = "d";
String point = ".";
String regex1 = "\\d+\\.\\d+";
String regex2 = Pattern.quote(digit + "+" + point + digit + "+");

Pattern numbers1 = Pattern.compile(regex1);
Pattern numbers2 = Pattern.compile(regex2);

System.out.println("Regex 1: " + regex1);

if (numbers1.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

System.out.println("Regex 2: " + regex2);

if (numbers2.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}
_

当然のことながら、上記のコードによって生成される出力は次のとおりです。

_Regex 1: \d+\.\d+
    Match
Regex 2: \Qd+.d+\E
    No match
_

つまり、_regex1_は_1.2_と一致しますが、_regex2_(「動的に」構築される)は一致しません(代わりに、リテラル文字列_d+.d+_と一致します)。

それで、各正規表現のメタ文字を自動的にエスケープする方法はありますか?

たとえば、_Java.util.regex.Pattern_に静的なescape()メソッドがある場合、

_Pattern.escape('.')
_

文字列_"\."_になりますが、

_Pattern.escape(',')
_

メタ文字ではないため、単に_","_を生成する必要があります。同様に、

_Pattern.escape('d')
_

_"\d"_は数字を表すために使用されるため、_'d'_を生成できます(ただし、_'d'_はリテラル_'d'_を意味する可能性があるため、この場合、エスケープは意味をなさない可能性があります) _'.'_)の場合のように、正規表現インターペッターが他の何かであると誤解した。

21
PNS

Javaまたは、引用符ではなく)特殊文字(メタ文字)をエスケープして正規表現として使用するためのオープンソースライブラリのメソッドはありますか?

私はこれがあなたがここで求めていることを100%確信していない。正規表現パターンで使用できる定数を作成する方法を探している場合は、_"\\"_を先頭に追加するだけで機能しますが、これを支援するNice Pattern.escape('.')関数はありません。

したがって、_"\\d"_(小数点文字ではなく文字列_\d_)に一致させようとする場合は、次のようにします。

_// this will match on \d as opposed to a decimal character
String matchBackslashD = "\\\\d";
// as opposed to
String matchDecimalDigit = "\\d";
_

Java文字列内の4つのスラッシュは、正規表現パターン内の2つのスラッシュになります。正規表現パターン内の2つのバックスラッシュは、バックスラッシュ自体と一致します。特別なもの。

_matchPeriod = "\\.";
matchPlus = "\\+";
matchParens = "\\(\\)";
... 
_

投稿で Pattern.quote(string) method を使用します。これにより、パターンが_"\\Q"_と_"\\E"_の間でラップされるので、特殊な正規表現文字(_+_、_._ 、_\\d_など)

23
Gray

私はこのパターンを書きました:

Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");

そして、このメソッドで使用します:

String escapeSpecialRegexChars(String str) {

    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0");
}

次に、たとえば次のように使用できます。

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*" + escapeSpecialRegexChars(text) + ".*");
}

エスケープした後、いくつかの正規表現を追加するため、これを行う必要がありました。そうでない場合は、単に\Q\Eを使用できます。

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}
25
Ferran Maylinch

正規表現マッチャーが、文字dではなく数字を探していることを知る唯一の方法は、文字(\d)をエスケープすることです。 Javaで正規表現エスケープ文字を入力するには、エスケープする必要があります(したがって、\\\になります)。そのため、特別な正規表現文字に二重のバックスラッシュを入力する方法はありません。

6
Attila

Pattern.quote(String s)ソートは、あなたが望むことをします。しかし、それは望み通りに少し残っています。実際には個々の文字をエスケープせず、文字列を\Q...\Eでラップするだけです。

探しているものを正確に実行するメソッドはありませんが、良いニュースは、Java正規表現ですべての特殊文字をエスケープするのは実際にはかなり簡単です:

regex.replaceAll("[\\W]", "\\\\$0")

なぜこれが機能するのですか?まあ、 Pattern のドキュメントでは、必ずしもエスケープする必要のないアルファベット以外の文字をエスケープすることが許可されていると具体的に述べています。

エスケープされたコンストラクトを示さないアルファベット文字の前にバックスラッシュを使用するとエラーになります。これらは、正規表現言語の将来の拡張のために予約されています。 バックスラッシュは、その文字がエスケープされていない構造の一部であるかどうかに関係なく、アルファベット以外の文字の前に使用できます。

たとえば、;は正規表現の特殊文字ではありません。ただし、エスケープすると、Patternは引き続き\;;として解釈します。以下にいくつか例を示します。

  • >\>になります。これは>と同等です
  • [\[のエスケープ形式である[になります
  • 88のままです。
  • \)\\\)になります。これは、\および(のエスケープ形式の連結です。

注:重要なのは「非アルファベット」の定義です。これは、ドキュメントでは「非Word 」文字、または文字セット[a-zA-Z_0-9]以外の文字。

1
wheeler

パターンにリテラル(\ [、\])とメタ文字([、])の両方が必要な場合があるため、グレーに同意します。そのため、いくつかのユーティリティを使用すると、最初にすべての文字をエスケープでき、その後、同じパターンに追加するメタ文字を追加できます。

1
nir

Groupsの間にある文字列をエスケープするには、このユーティリティ関数escapeQuotes()を使用しますセットRegualrExpression

エスケープする正規表現リテラルのリスト <([{\^-=$!|]})?*+.>

_public class RegexUtils {
    static String escapeChars = "\\.?![]{}()<>*+-=^$|";
    public static String escapeQuotes(String str) {
        if(str != null && str.length() > 0) {
            return str.replaceAll("[\\W]", "\\\\$0"); // \W designates non-Word characters
        }
        return "";
    }
}
_

Pattern クラスから、バックスラッシュ文字_('\')_はエスケープされた構造を導入するのに役立ちます。文字列リテラル"\(hello\)"は不正であり、コンパイル時エラーを引き起こします。文字列(hello)に一致させるには、文字列リテラル"\\(hello\\)"を使用する必要があります。

:一致する文字列_(hello)_およびグループとの正規表現は_(\(hello\))_です。ここでフォームを作成すると、以下に示すように一致した文字列をエスケープするだけで済みます。 _Test Regex online_

_public static void main(String[] args) {
    String matched = "(hello)", regexExpGrup = "(" + escapeQuotes(matched) + ")";
    System.out.println("Regex : "+ regexExpGrup); // (\(hello\))
}
_
0
Yash

つかいます

pattern.compile("\"");
String s= p.toString()+"yourcontent"+p.toString();

結果をそのままyourcontentとして返します

0
kavita