我是否总是需要在不是“文字”的字符串中转义元字符?
似乎在正则表达式处理期间拒绝包含字符{
或}
的字符串。 我可以理解这些是保留字符,我需要逃避它们,所以如果我这样做:
string.replaceAll("\\" + pattern);
这是有效的,其中pattern
是以{
开头的任何字符串。
问题:是否有办法避免已经包含此类元组的字符串出现此类问题,以便自动处理? 在我看来它应该与在字符串文字中添加双引号相比,接受字符串作为已经具有双引号的输入
使用Pattern.quote(String)
:
public static String quote(String s)
返回指定
String
的文字模式String
。此方法生成一个
String
,该String
可用于创建与字符串s
匹配的Pattern
,就好像它是文字模式一样。输入序列中的元字符或转义序列将没有特殊含义。
参数:
s
– 要文字化的字符串
返回:
文字字符串替换
以来:
1.5
您可以使用
java.util.regex.Pattern.quote(java.lang.String)
转义正则表达式使用的元字符。
TL; DR
- 如果你需要正则表达式语法使用
replaceAll
或replaceFirst
, - 如果您希望将
target/replacement
对视为文字,请使用replace
(它还会替换所有出现的目标)。
大多数人都对在String类中替换方法的不幸命名感到困惑,这些方法是:
-
replaceAll(String, String)
-
replaceFirst(String, String)
-
replace(CharSequence, CharSequence)
-
replace(char, char)
由于replaceAll
方法明确声称它替换了所有可能的目标,因此人们认为replace
方法并不能保证这种行为,因为它不包含All
后缀。
但这种假设是错误的。
这些方法之间的主要区别如下表所示:
╔═════════════════════╦═══════════════════════════════════════════════════════════════════╗ ║ ║ replaced targets ║ ║ ╠════════════════════════════════════╦══════════════════════════════╣ ║ ║ ALL found ║ ONLY FIRST found ║ ╠══════╦══════════════╬════════════════════════════════════╬══════════════════════════════╣ ║ ║ supported ║ replaceAll(String, String) ║ replaceFirst(String, String) ║ ║regex ╠══════════════╬════════════════════════════════════╬══════════════════════════════╣ ║syntax║ not ║ replace(CharSequence, CharSequence)║ \/ ║ ║ ║ supported ║ replace(char, char) ║ /\ ║ ╚══════╩══════════════╩════════════════════════════════════╩══════════════════════════════╝
现在,如果您不需要使用正则表达式语法使用方法而不期望它,但它将target
和replacement
视为文字。
所以代替replaceAll(regex, replacement)
使用replace(literal, replacement)
。
如您所见,有两个重载的重载版本。 它们都应该适合你,因为它们不支持正则表达式语法。 它们之间的主要区别在于:
-
replace(char target, char replacement)
只是创建新的字符串,并用原始字符串中的字符或您决定替换的字符(取决于它是否等于目标字符)填充它 -
replace(CharSequence target, CharSequence replacement)
本质上等同于replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement.toString())
,这意味着它与replaceAll
相同但是(这意味着它在内部使用正则表达式引擎)但它会逃避target
使用的正则表达式元字符并自动replacement
您不需要任何额外的代码,只需要\Q
和\E
构造,如Java的Pattern类中所述 。
例如,在以下代码中:
String foobar = "crazyPassword=f()ob@r{}+"; Pattern regex = Pattern.compile("\\Q" + foobar "\\E");
模式将编译,foobar的特殊字符不会被解释为正则表达式字符。 在这里看演示。
它唯一不匹配的是输入包含文字\E
如果你也需要解决这个问题,请在评论中告诉我,我会编辑添加。