ユーザーが送信しようとしているメッセージとメッセージテンプレートを一致させるアプリケーションを作成しようとしています。メッセージのマッチングにJava正規表現を使用しています。テンプレート/メッセージに特殊文字が含まれている可能性があります。
正規表現を機能させ、可能な限り多くの場合に一致させるために、エスケープする必要がある特殊文字の完全なリストをどのように取得しますか?
Java正規表現ですべての特殊文字をエスケープするための普遍的な解決策はありますか?
あなたはパターンクラスのJavadocを見ることができます: http://docs.Oracle.com/javase/8/docs/api/Java/util/regex/Pattern.html
特別な意味ではなく通常の文字が必要な場合は、そこにリストされている文字をすべてエスケープする必要があります。
もっと簡単な解決策として、テンプレートを\ Qと\ Eの間に置くことができます - それらの間のすべてはエスケープされていると見なされます。
\.[]{}()<>*+-=!?^$|
]
と}
)は、同じ種類の括弧を開いた後にのみエスケープする必要があります。[]
-括弧内のいくつかの文字(+
や-
など)は、エスケープなしで動作することがあります。String Literals/Metacharacters のドキュメントページによると、それらは以下のとおりです。
<([{\^-=$!|]})?*+.>
また、そのリストをコード内のどこかで参照させておくのはかっこいいでしょうが、それがどこにあるのか私にはわかりません...
@ SorinによるJava Patternのドキュメントの提案では、逃げるべき文字が少なくともあるように思えます。
\.[{(*+?^$|
みんなの言ったことを組み合わせると、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");
}
コインの反対側では、特殊文字= allChars - number - ABC - スペースがアプリのコンテキストで使用されている場合は、このように見える「char以外」の正規表現を使用する必要があります。
String regepx = "[^\\s\\w]*";
Pattern.quote(String s)
ソートはあなたが望むことをします。しかし、それは望ましいことを少し残しています。実際には個々の文字をエスケープするのではなく、文字列を\Q...\E
で囲むだけです。
あなたが探しているものを正確に実行するメソッドはありませんが、良いニュースは、Java正規表現の中の特殊文字をすべてエスケープするのは実際にはかなり簡単なことです。
regex.replaceAll("[\\W]", "\\\\$0")
なぜこれが機能するのですか?ええと、 Pattern
のドキュメントには、必ずしもエスケープする必要のないアルファベット以外の文字をエスケープすることは許可されていることが明確に記載されています。
エスケープ構文を示さないアルファベット文字の前にバックスラッシュを使用するとエラーになります。これらは将来の正規表現言語への拡張のために予約されています。 バックスラッシュは、その文字がエスケープされていない構文の一部であるかどうかにかかわらず、アルファベット以外の文字の前に使用できます。
たとえば、;
は正規表現では特殊文字ではありません。ただし、エスケープしても、Pattern
は\;
を;
として解釈します。もう少し例を挙げましょう。
>
は\>
になり、これは>
と同等です。[
は、\[
のエスケープ形式である[
になります。8
はまだ8
です。\)
は\\\)
になります。これは\
と(
を連結したエスケープ形式です。注:重要なのは「アルファベット以外の」の定義です。これは、この文書では実際には「なし - を意味します。Word "文字、または文字セット[a-zA-Z_0-9]
の外側の文字。
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);
}
答えは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
私はあなたの質問を完全に理解しているかどうかわからないが、私はあなたが見るべきであると思います Matcher.quoteReplacement()