我需要转义非“字面量”字符串中的元字符吗?

7

在正则表达式处理过程中,包含字符 {} 的字符串似乎会被拒绝。我可以理解这些是保留字符,需要转义,所以如果我这样做:

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

这个代码可以正常工作,其中pattern是以{开头的任何字符串。

问题:有没有一种方法可以自动处理包含这些元字符的字符串,以避免这样的问题?对我来说,它应该与在字符串字面上添加双引号与接受已经具有双引号的输入字符串相同。


2
请使用replace而不是replaceAll - Pshemo
@Pshemo:它们的行为不同吗? - Jim
阅读文档...有 replace(char, char)replace(String, String) 两种方法都可以满足你的需求。 - Pshemo
如果任何答案对您有帮助,请接受它以指出正确的解决方案! - Fabian Damken
4个回答

8
使用Pattern.quote(String)函数:
public static String quote(String s)

Returns a literal pattern String for the specified String.

This method produces a String that can be used to create a Pattern that would match the string s as if it were a literal pattern.

Metacharacters or escape sequences in the input sequence will be given no special meaning.

Parameters:
    s - The string to be literalized
Returns:
    A literal string replacement
Since:
    1.5


4

您可以使用

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

为了避免被正则表达式使用的元字符影响,可以使用转义字符。

3

简述:

  • 如果您需要正则表达式语法,请使用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相同(这意味着它在内部使用正则表达式引擎),但它自动为我们转义了targetreplacement中使用的正则表达式元字符

@downvoter能否指出这个答案有什么问题,以便我改进它? - Pshemo
很好的信息,如果我想深入学习Java正则表达式,你会推荐我哪些材料呢? :) - Muhammad
1
@Muhammad http://www.regular-expressions.info/tutorial.html是我至今发现的关于纯正则表达式和各种语言实现的最好教程。Java正则表达式教程也不错https://docs.oracle.com/javase/tutorial/essential/regex/,但你还应该阅读Pattern类的文档https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html,其中包含了关于Java中支持的正则表达式机制的大量信息。 - Pshemo

0

您不需要任何额外的代码,只需使用\Q\E结构即可,这些结构在Java的Pattern类中有详细说明。

例如,在以下代码中:

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

该模式将被编译,foobar的特殊字符不会被解释为正则表达式字符。请查看演示此处

它唯一无法匹配的是输入包含文字\E的情况。如果您也需要解决这个问题,请在评论中告诉我,我会编辑并添加相应内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接