我正在尝试创建一个将消息模板与用户尝试发送的消息相匹配的应用程序。我正在使用 Java 正则表达式来匹配消息。模板/消息可能包含特殊字符。
如何获得需要转义的特殊字符的完整列表,以便我的正则表达式在最大可能的情况下工作和匹配?
是否有一个通用的解决方案来转义 Java 正则表达式中的所有特殊字符?
您可以查看 Pattern 类的 javadoc:http: //docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
如果您想要常规字符而不是特殊含义,则需要转义此处列出的任何字符。
作为一个可能更简单的解决方案,您可以将模板放在 \Q 和 \E 之间 - 它们之间的所有内容都被视为转义。
\.[]{}()<>*+-=!?^$|
]
和}
) 只需要在打开相同类型的括号后进行转义。[]
-brackets 中,某些字符(如+
和-
)有时会在没有转义的情况下工作。结合大家所说,我提出以下建议,以保持 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");
}
虽然答案是针对 Java 的,但是代码可以很容易地从我想出的这个 Kotlin 字符串扩展中改编(改编自 @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
在@Sorin 对 Java Pattern 文档的建议中,看起来要转义的字符至少是:
\.[{(*+?^$|
Pattern.quote(String s)
那种做你想做的事。然而,它还有一些不足之处。它实际上并没有转义单个字符,只是用\Q...\E
.
没有一种方法可以完全满足您的需求,但好消息是,在 Java 正则表达式中转义所有特殊字符实际上相当简单:
regex.replaceAll("[\\W]", "\\\\$0")
为什么这行得通?好吧,文档Pattern
专门说它允许转义不一定必须转义的非字母字符:
在任何不表示转义结构的字母字符之前使用反斜杠是错误的;这些是为将来对正则表达式语言的扩展而保留的。可以在非字母字符之前使用反斜杠,无论该字符是否是未转义结构的一部分。
例如,;
不是正则表达式中的特殊字符。但是,如果你逃避它,Pattern
仍然会解释\;
为;
. 这里还有几个例子:
>
变成\>
相当于>
[
成为\[
的转义形式[
8
还在8
。\)
成为\\\)
它是转义形式\
和(
连接。注意:关键是“非字母”的定义,在文档中真正的意思是“非单词”字符,或者字符集之外的字符[a-zA-Z_0-9]
。
在硬币的另一面,如果特殊字符 = allChars - 数字 - ABC - 在您的应用程序上下文中的空间,您应该使用看起来像这样的“非字符”正则表达式。
String regepx = "[^\\s\\w]*";
假设您拥有并信任(具有权威性)Java regex 使用的转义字符列表(如果这些字符暴露在某个 Pattern 类成员中会很好),如果确实有必要,您可以使用以下方法来转义字符:
private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };
private static String regexEscape(char character) {
for (char escapeChar : escapeChars) {
if (character == escapeChar) {
return "\\" + character;
}
}
return String.valueOf(character);
}