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


108

メッセージテンプレートとユーザーが送信しようとしているメッセージを照合するアプリケーションを作成しようとしています。メッセージの照合にJava正規表現を使用しています。テンプレート/メッセージには特殊文字が含まれている場合があります。

正規表現を最大限に活用して一致させるためにエスケープする必要がある特殊文字の完全なリストを取得するにはどうすればよいですか?

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

回答:


94

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

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

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


43
\ Qと\ Eを覚えにくい場合は、代わりにPattern.quote( "...")を使用できます
mkdev

19
私はあなたが実際にそれらを述べていたらいいのに
アレクサンドル・デュビンスキー2014年

なぜ、@ AleksandrDubinsky?
ソリン2014年

55
@Sorinオフサイトのリソースにリンクするだけでなく、答えの中に答えを述べるのはStack Exchangeの精神(いや、ポリシー?)だからです。さらに、そのページには明確なリストもありません。リストはdocs.oracle.com/javase/tutorial/essential/regex/literals.htmlにありますが、何が起こるかを説明せずに、「特定の状況では、上記の特殊文字がメタ文字として扱われない場合があります」と記載されてます。脱出を試みた場合。要するに、この質問は良い答えに値します。
Aleksandr Dubinsky 2014年

8
「それらの間のすべて[ \Q\E]はエスケープされていると見なされます」 —他\Qのとを除き\Eます(元の正規表現内で発生する可能性があります)。したがって、ここPattern.quote提案されているように使用し、ホイールを再発明しない方が良いでしょう。
Sasha

92
  • 正規表現でエスケープする必要があるJava文字は次のとおりです。
    \.[]{}()<>*+-=!?^$|
  • 2つの閉じ括弧(]および})は、同じタイプの括弧を開いた後にのみエスケープする必要があります。
  • 中には、[]一部の文字(のような-brackets +とは-)エスケープせずに、時には仕事をします。

エスケープせずにそれらの文字を許可する方法はありますか?
ドミニカ

1
文字をエスケープするとは、文字を演算子として解釈するのではなく、許可することを意味します。
Tobi G.

4
範囲を定義するために使用されるため、エスケープさ-れてい[]ないものは常に機能するとは限りません。脱出する方が安全です。たとえば、パターン[-][-)]は文字列と一致します-が、とは一致しません[(-)]
Kenston Choi 2016

1
受け入れられた答えは質問に答えますが、クイックリストを探しているときは、この答えの方が役に立ちました。
Old Nick

-=!必ずしもエスケープする必要はありません。コンテキストによって異なります。たとえば、単一の文字として、それらは定数の正規表現として機能します。
Hawk

29

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

Pattern.quote("$test");

あなたは完全に単語と一致します $test


これが最も評価の高い回答ではないのはなぜですか?エスケープが必要なすべての文字をリストするという複雑な詳細に入る必要はなく、JDKの一部です。追加のコードを記述する必要はありません。シンプル!
Volksman

17

文字列リテラル/メタキャラクターのドキュメントページによると、次のとおりです。

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

また、そのリストがコードのどこかで参照されていると便利ですが、どこにあるかわかりません...


11
String escaped = tnk.replaceAll("[\\<\\(\\[\\{\\\\\\^\\-\\=\\$\\!\\|\\]\\}\\)\\?\\*\\+\\.\\>]", "\\\\$0");
marbel82 2016年

1
パターンのjavadocは、エスケープされた構成を示さないアルファベット文字の前にバックスラッシュを使用するとエラーになると述べています、その文字がエスケープされていない構成の一部であるかどうかに関係なく、アルファベット以外の文字の前にバックスラッシュを使用できます。したがって、はるかに単純な正規表現で十分です。s.replaceAll("[\\W]", "\\\\$0")ここで、は\W単語以外の文字を指定します。
Joe Bowbeer 2017

6

誰もが言ったことを組み合わせて、私は以下を提案します。RegExpに特有の文字のリストを独自の文字列に明確にリストし、数千の「\\」を視覚的に解析する必要がないようにします。これは私にはかなりうまくいくようです:

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

5

@SorinによるJavaパターンドキュメントの提案では、エスケープする文字は少なくとも次のように見えます。

\.[{(*+?^$|

4
String escaped = regexString.replaceAll("([\\\\\\.\\[\\{\\(\\*\\+\\?\\^\\$\\|])", "\\\\$1");
fracz 2014年

2
)もエスケープする必要があり、文字クラスの内部か外部かに応じて、エスケープする文字が多くなる可能性があります。その場合Pattern.quote、文字クラスの内部と外部の両方で使用するために文字列をエスケープするのに非常に適しています。
nhahtdh

3

Pattern.quote(String s)何をしたいんの一種。しかしそれは望まれるために少し残しておきます。実際に個々の文字をエスケープするのではなく、文字列をで囲みます\Q...\E

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

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

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

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

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

  • >\>等価になる>
  • [となり\[のエスケープ形式であります[
  • 8まだ8です。
  • \)となり\\\)のエスケープ形式である\(連結。

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


2

コインの反対側では、特殊文字= allChars-数値-ABC-アプリコンテキスト内のスペースの場合、次のような「非文字」正規表現を使用する必要があります。

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

2

答えは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


1

Java正規表現が使用するエスケープ文字のリストがあり(信頼できるものである)信頼している(これらの文字が一部のパターンクラスメンバーで公開されている場合は便利です)と仮定すると、本当に必要な場合は次のメソッドを使用して文字をエスケープできます。

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

private static String regexEscape(char character) {
    for (char escapeChar : escapeChars) {
        if (character == escapeChar) {
            return "\\" + character;
        }
    }
    return String.valueOf(character);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.