我正在尝试创建一个应用程序,该应用程序将消息模板与用户尝试发送的消息进行匹配。我正在使用Java正则表达式来匹配消息。模板/消息可能包含特殊字符。
我如何获取需要转义的特殊字符的完整列表,以使我的正则表达式在最大可能的情况下起作用并匹配?
是否有通用的解决方案可以在Java正则表达式中转义所有特殊字符?
我正在尝试创建一个应用程序,该应用程序将消息模板与用户尝试发送的消息进行匹配。我正在使用Java正则表达式来匹配消息。模板/消息可能包含特殊字符。
我如何获取需要转义的特殊字符的完整列表,以使我的正则表达式在最大可能的情况下起作用并匹配?
是否有通用的解决方案可以在Java正则表达式中转义所有特殊字符?
Answers:
您可以查看Pattern类的javadoc:http : //docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
如果需要常规字符而不是特殊含义,则需要转义那里列出的任何字符。
作为一个可能更简单的解决方案,您可以将模板放在\ Q和\ E之间-它们之间的所有内容都被认为是转义的。
\.[]{}()<>*+-=!?^$|
]
和}
)。[]
括号中,某些字符(如+
和-
)有时可以正常运行而不会转义。-
内[]
可能并不总是可行的,因为它是用来定义范围。逃避它更安全。例如,模式[-]
和[-)]
匹配字符串,-
但不匹配[(-)]
。
-=!
不一定需要进行转义,这取决于上下文。例如,作为单个字母,它们可以用作常量正则表达式。
String escaped = tnk.replaceAll("[\\<\\(\\[\\{\\\\\\^\\-\\=\\$\\!\\|\\]\\}\\)\\?\\*\\+\\.\\>]", "\\\\$0");
s.replaceAll("[\\W]", "\\\\$0")
其中\W
指定非单词字符。
结合每个人的讲话,我提出以下建议,以使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");
}
根据@Sorin对Java Pattern文档的建议,看起来至少要转义的字符是:
\.[{(*+?^$|
String escaped = regexString.replaceAll("([\\\\\\.\\[\\{\\(\\*\\+\\?\\^\\$\\|])", "\\\\$1");
)
还必须转义,并且取决于您位于字符类的内部还是外部,可以有更多的字符要转义,在这种情况下Pattern.quote
,转义字符串以供在字符类的内部和外部使用都做得很好。
在Pattern.quote(String s)
那种你想要做什么。但是,它还有一点不足。它实际上并不会转义单个字符,而只是使用来包装字符串\Q...\E
。
没有一种方法可以完全满足您的需求,但是好消息是,实际上转义Java正则表达式中的所有特殊字符非常简单:
regex.replaceAll("[\\W]", "\\\\$0")
为什么这样做?好吧,Pattern
专门针对的文档说,它允许转义不一定要转义的非字母字符:
在任何不表示转义结构的字母字符之前使用反斜杠是一个错误;这些保留用于将来对正则表达式语言的扩展。可以在非字母字符之前使用反斜杠,而不管该字符是否为未转义构造的一部分。
例如,;
在正则表达式中不是特殊字符。但是,如果您Pattern
将其转义,仍将解释\;
为;
。以下是一些示例:
>
变成\>
等于>
[
成为\[
哪个是逃脱形式[
8
还是8
。\)
成为\\\)
的转义形式\
并将其(
连接起来。注意:关键是“非字母”的定义,它在文档中实际上表示“非单词 ”字符或字符集之外的字符[a-zA-Z_0-9]
。
虽然答案是针对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
假设您拥有并信任(具有权威性)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);
}