我是否总是需要在不是"字面值的字符串中转义元字符"?

时间:2015-10-30 20:08:41

标签: java regex string

在正则表达式处理期间,似乎拒绝包含字符{}的字符串。我可以理解这些是保留字符,如果我这样做,我需要逃避它们:

string.replaceAll("\\" + pattern);

这是有效的,其中pattern是以{开头的任何字符串。

问题:有没有办法避免已经包含此类元集的字符串出现此类问题,以便自动处理?在我看来它应该与在字符串文字中添加双引号相对于接受字符串作为已经具有双引号的输入

相同

4 个答案:

答案 0 :(得分:8)

使用Pattern.quote(String)

public static String quote(String s)
     

返回指定String的文字模式String

     

此方法生成String,可用于创建与Pattern字符串匹配的s,就好像它是文字模式一样。

     

输入序列中的元字符或转义序列没有特殊含义。

     

<强>参数:
  s - 要文字化的字符串
  的返回:
  文字字符串替换
  的时间:
  1.5

答案 1 :(得分:4)

您可以使用

java.util.regex.Pattern.quote(java.lang.String)

转义正则表达式使用的元字符。

答案 2 :(得分:3)

TL; DR

  • 如果您需要正则表达式语法,请使用replaceAllreplaceFirst
  • 如果您希望将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)                ║              /\              ║
╚══════╩══════════════╩════════════════════════════════════╩══════════════════════════════╝

现在,如果您不需要使用正则表达式语法使用方法并不期望它,但它会将targetreplacement视为文字。

而不是replaceAll(regex, replacement)

使用replace(literal, replacement)

如您所见,replace有两个重载版本。他们都应该为你工作,因为他们不支持正则表达式语法。它们之间的主要区别在于:

  • replace(char target, char replacement)只是创建一个新字符串并用原始字符串中的字符或您决定替换的字符填充它(取决于它是否等于目标字符)

  • replace(CharSequence target, CharSequence replacement)基本上相当于 replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement.toString())表示它与replaceAll相同但是(这意味着它在内部使用正则表达式引擎)但是 它会转义target和{{1}中使用的正则表达式元字符我们自动

答案 3 :(得分:0)

You don't need any extra code, just the \Q and \E constructs, as documented in Java's Pattern class.

For example, in the following code:

String foobar = "crazyPassword=f()ob@r{}+";
Pattern regex = Pattern.compile("\\Q" + foobar "\\E");

the pattern would compile and foobar's special characters would not be interpreted as regex characters. See demo here.

The only thing that it won't match is where the input contains a literal \E. If you need to solve that problem too, just let me know in a comment and I'll edit to add that.