346

Java 是否有内置的方法来转义任意文本,以便可以将其包含在正则表达式中?例如,如果我的用户输入“$5”,我想完全匹配它而不是输入结束后的“5”。

4

8 回答 8

476

Java 1.5 开始,是的

Pattern.quote("$5");
于 2008-09-12T23:39:52.123 回答
121

在我看到以下示例之前,我并不清楚Pattern.quote和之间的区别Matcher.quoteReplacement

s.replaceFirst(Pattern.quote("text to replace"), 
               Matcher.quoteReplacement("replacement text"));
于 2008-09-12T23:52:14.310 回答
32

响应可能为时已晚,但您也可以使用Pattern.LITERAL,它会在格式化时忽略所有特殊字符:

Pattern.compile(textToFormat, Pattern.LITERAL);
于 2016-03-14T15:04:02.993 回答
13

我想你追求的是\Q$5\E. 另见Pattern.quote(s)Java5中介绍。

有关详细信息,请参阅模式javadoc。

于 2008-09-12T23:42:16.220 回答
10

首先,如果

  • 你使用 replaceAll()
  • 你不要使用 Matcher.quoteReplacement()
  • 要替换的文本包括 $1

它不会在最后放一个 1 。它将查看第一个匹配组的搜索正则表达式并将其插入。这就是替换文本中 $1、$2 或 $3 的含义:来自搜索模式的匹配组。

我经常将长字符串插入 .properties 文件,然后从中生成电子邮件主题和正文。事实上,这似乎是在 Spring Framework 中执行 i18n 的默认方式。我将 XML 标记作为占位符放入字符串中,并使用 replaceAll() 将 XML 标记替换为运行时的值。

我遇到了一个问题,用户输入带有美元符号的美元和美分数字。replaceAll() 被它呛住了,以下显示在 stracktrace 中:

java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)

在这种情况下,用户在其输入中的某处输入了“$3”,replaceAll() 在搜索正则表达式中查找第三个匹配组,但没有找到,然后吐了。

鉴于:

// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user's input

更换

msg = msg.replaceAll("<userInput \\/>", userInput);

msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));

解决了这个问题。用户可以毫无问题地输入任何类型的字符,包括美元符号。它的行为完全符合您的预期。

于 2012-08-14T15:00:27.453 回答
9

要拥有受保护的模式,您可以用“\\\\”替换所有符号,数字和字母除外。之后,您可以在该受保护模式中放入您的特殊符号,以使该模式不像愚蠢的引用文本那样工作,而是真正像一个模式,而是您自己的模式。无用户特殊符号。

public class Test {
    public static void main(String[] args) {
        String str = "y z (111)";
        String p1 = "x x (111)";
        String p2 = ".* .* \\(111\\)";

        p1 = escapeRE(p1);

        p1 = p1.replace("x", ".*");

        System.out.println( p1 + "-->" + str.matches(p1) ); 
            //.*\ .*\ \(111\)-->true
        System.out.println( p2 + "-->" + str.matches(p2) ); 
            //.* .* \(111\)-->true
    }

    public static String escapeRE(String str) {
        //Pattern escaper = Pattern.compile("([^a-zA-z0-9])");
        //return escaper.matcher(str).replaceAll("\\\\$1");
        return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1");
    }
}
于 2012-11-15T20:27:30.873 回答
5

Pattern.quote("blabla") 效果很好。

Pattern.quote() 效果很好。它用字符“ \Q ”和“ \E ”将句子括起来,如果它确实转义了“\Q”和“\E”。但是,如果您需要进行真正的正则表达式转义(或自定义转义),则可以使用以下代码:

String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));

此方法返回:Some/\s/wText*/\,**

代码示例和测试:

String someText = "Some\\E/s/wText*/,**";
System.out.println("Pattern.quote: "+ Pattern.quote(someText));
System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
于 2017-07-31T12:26:41.050 回答
-3

^(否定)符号用于匹配不在字符组中的内容。

这是正则表达式的链接

这是关于否定的图像信息:

关于否定的信息

于 2018-06-22T15:00:14.100 回答