38

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+)。

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

たとえば、に静的escape()メソッドがあったjava.util.regex.Pattern場合、の出力は

Pattern.escape('.')

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

Pattern.escape(',')

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

Pattern.escape('d')

"\d"は数字を表すために使用されるため、を生成でき'd'ます(ただし、この場合、エスケープは意味をなさない場合があります。これは、正規表現の介入者が他の何かと誤解しない'd'文字通りを意味する場合があります)。'd''.'

4

7 に答える 7

36

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

正規表現パターンで使用できる定数を作成する方法を探している場合は、それらの前に付けるだけで機能する"\\"はずですがPattern.escape('.')、これを支援する優れた関数はありません。

したがって、 ( 10進文字の代わりに"\\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)メソッドを使用します。"\\Q"このメソッドはパターンをとの間でラップするため、文字列に特殊な正規表現文字( 、、など)が含ま"\\E"れている場合でも文字列を一致させることができます。+.\\d

于 2012-05-19T12:11:11.960 に答える
32

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

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) + ".*");
}

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

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}
于 2014-09-15T17:25:34.037 に答える
8

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

于 2012-05-19T10:47:20.740 に答える
5

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

探していることを正確に実行する方法はありませんが、幸いなことに、Java正規表現のすべての特殊文字をエスケープするのは実際にはかなり簡単です。

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

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

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

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

  • >\>に相当するものになります>
  • [\[のエスケープされた形式になります[
  • 8まだ8です。
  • \)\\\)のエスケープされた形式\(連結されたものになります。

注:重要なのは「非アルファベット」の定義です。これは、ドキュメントでは実際には「非単語」文字、または文字セット外の文字を意味し[a-zA-Z_0-9]ます。

于 2019-05-24T21:39:03.170 に答える
3

のグループセット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\))
}
于 2019-01-08T08:00:27.100 に答える
2

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

于 2013-10-09T01:49:04.267 に答える
1

使用する

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

そのまま結果yourcontentが出ます

于 2017-04-28T09:57:33.520 に答える