web-dev-qa-db-ja.com

正規表現でエスケープする必要があるすべての特殊文字のリスト

ユーザーが送信しようとしているメッセージとメッセージテンプレートを一致させるアプリケーションを作成しようとしています。メッセージのマッチングにJava正規表現を使用しています。テンプレート/メッセージに特殊文字が含まれている可能性があります。

正規表現を機能させ、可能な限り多くの場合に一致させるために、エスケープする必要がある特殊文字の完全なリストをどのように取得しますか?

Java正規表現ですべての特殊文字をエスケープするための普遍的な解決策はありますか?

85
Avinash Nair

あなたはパターンクラスのJavadocを見ることができます: http://docs.Oracle.com/javase/8/docs/api/Java/util/regex/Pattern.html

特別な意味ではなく通常の文字が必要な場合は、そこにリストされている文字をすべてエスケープする必要があります。

もっと簡単な解決策として、テンプレートを\ Qと\ Eの間に置くことができます - それらの間のすべてはエスケープされていると見なされます。

77
Sorin
  • 正規表現でエスケープする必要があるJava文字は次のとおりです。
    \.[]{}()<>*+-=!?^$|
  • 閉じ括弧のうちの2つ(]})は、同じ種類の括弧を開いた後にのみエスケープする必要があります。
  • []-括弧内のいくつかの文字(+-など)は、エスケープなしで動作することがあります。
76
Tobi G.

エスケープするには、これを Java 1.5 から使用することができます。

Pattern.quote("$test");

$testという単語と完全に一致します

22
madx

String Literals/Metacharacters のドキュメントページによると、それらは以下のとおりです。

<([{\^-=$!|]})?*+.>

また、そのリストをコード内のどこかで参照させておくのはかっこいいでしょうが、それがどこにあるのか私にはわかりません...

15
Bohdan

@ SorinによるJava Patternのドキュメントの提案では、逃げるべき文字が少なくともあるように思えます。

\.[{(*+?^$|
5
pete

みんなの言ったことを組み合わせると、RegExpに特別な文字のリストをそれぞれのStringに明確にリストしたままにし、何千もの "\\"を視覚的に解析しなくても済むように、以下を提案します。これは私にとってはかなりうまくいくようです。

final String regExSpecialChars = "<([{\\^-=$!|]})?*+.>";
final String regExSpecialCharsRE = regExSpecialChars.replaceAll( ".", "\\\\$0");
final Pattern reCharsREP = Pattern.compile( "[" + regExSpecialCharsRE + "]");

String quoteRegExSpecialChars( String s)
{
    Matcher m = reCharsREP.matcher( s);
    return m.replaceAll( "\\\\$0");
}
4
NeuroDuck

コインの反対側では、特殊文字= allChars - number - ABC - スペースがアプリのコンテキストで使用されている場合は、このように見える「char以外」の正規表現を使用する必要があります。

String regepx = "[^\\s\\w]*";
2
Bo6Bear

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

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

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

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

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

たとえば、;は正規表現では特殊文字ではありません。ただし、エスケープしても、Pattern\;;として解釈します。もう少し例を挙げましょう。

  • >\>になり、これは>と同等です。
  • [は、\[のエスケープ形式である[になります。
  • 8はまだ8です。
  • \)\\\)になります。これは\(を連結したエスケープ形式です。

注:重要なのは「アルファベット以外の」の定義です。これは、この文書では実際には「なし - を意味します。Word "文字、または文字セット[a-zA-Z_0-9]の外側の文字。

2
wheeler

Java regexが使用するエスケープ文字のリスト(権威あるため)を所有し、信頼していると仮定すると(これらの文字がパターンクラスメンバーで公開されている場合はニースになります)、次のメソッドを使用して文字をエスケープできます本当に必要な場合:

private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };

private static String regexEscape(char character) {
    for (char escapeChar : escapeChars) {
        if (character == escapeChar) {
            return "\\" + character;
        }
    }
    return String.valueOf(character);
}
0
brcolow

答えはJavaですが、コードは私が思いついたこのKotlin String拡張機能から簡単に適応させることができます(提供されている@brcolowから適応):

private val escapeChars = charArrayOf(
    '<',
    '(',
    '[',
    '{',
    '\\',
    '^',
    '-',
    '=',
    '$',
    '!',
    '|',
    ']',
    '}',
    ')',
    '?',
    '*',
    '+',
    '.',
    '>'
)

fun String.escapePattern(): String {
    return this.fold("") {
      acc, chr ->
        acc + if (escapeChars.contains(chr)) "\\$chr" else "$chr"
    }
}

fun main() {
    println("(.*)".escapePattern())
}

\(\.\*\)を印刷します

ここで実際に確認してください https://pl.kotl.in/h-3mXZkNE

0
pocesar

私はあなたの質問を完全に理解しているかどうかわからないが、私はあなたが見るべきであると思います Matcher.quoteReplacement()

0
mkoryak