当前位置:  开发笔记 > 编程语言 > 正文

如何在Java中转义正则表达式的文本

如何解决《如何在Java中转义正则表达式的文本》经验,为你挑选了6个好方法。

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



1> Mike Stone..:

从Java 1.5开始,是的:

Pattern.quote("$5");


请注意,这不会逃脱字符串本身,而是使用`\ Q`和`\ E`包装它.这可能会导致意外的结果,例如`Pattern.quote("*.wav").replaceAll("*",".*")`将导致`\ Q.*.wav\E`而不是`.*\.wav`,正如您所料.
我只是想指出这种转义方法也适用于你之后引入**的表达式.这可能会令人惊讶.如果你做"鼠标".toUpperCase().replaceAll("OUS","ic")`它将返回`MicE`.你不会期望它返回`MICE`,因为你没有在`ic`上应用`toUpperCase()`.在我的例子中,`quote()`也适用于`.``insertet由`replaceAll()`.你必须做一些其他事情,也许`.replaceAll("*","\\ E.*\\ Q")`会起作用,但那是违反直觉的.
@Paramaeleon为什么你会期望foo(x).bar()== x.bar()?
@Paramaeleon我认为你误解了用例.
@Paramaleon如果它通过添加单个转义符确实起作用,你的初始示例仍然不会做你想要的...如果它单独转义字符,它会将`*.wav`转换为正则表达式模式`\*\.wav` ,并且replaceAll会把它变成`\.*\.wav`,这意味着它将匹配名称由任意数量的句点后跟`.wav`的文件.你很可能需要`replaceAll("\\*",".*")`如果他们选择了更脆弱的实现,依赖于识别所有可能的主动正则表达式字符串并单独逃避它们...那么容易吗?

2> Pavel Feldma..:

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

s.replaceFirst(Pattern.quote("text to replace"), 
               Matcher.quoteReplacement("replacement text"));


具体来说,`Pattern.quote`替换正则表达式搜索字符串中的特殊字符,如.| +()等,而'Matcher.quoteReplacement`替换替换字符串中的特殊字符,如\ 1作为反向引用.
我不同意.Pattern.quote用\ Q和\ E包装其参数.它不会逃避特殊字符.
Matcher.quoteReplacement("4 $&%$")生成"4\$&%\ $".它逃脱了特殊的角色.
换句话说:`quoteReplacement`只关心两个符号`$`和`\`,它们可以在替换字符串中用作反向引用`$ 1`或`\ 1`.因此,它不得用于逃避/引用正则表达式.

3> Androidme..:

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

Pattern.compile(textToFormat, Pattern.LITERAL);



4> Rob Oxspring..:

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

有关详细信息,请参见Pattern javadoc.


请注意,如果您知道输入,那么字面上使用\ Q和\ E就可以了.Pattern.quote(s)还将处理文本实际包含这些序列的情况.

5> Meower68..:

首先,如果

你使用replaceAll()

你不要使用Matcher.quoteReplacement()

要替换的文本包括1美元

它不会在最后放1.它将查看第一个匹配组和子THAT的搜索正则表达式.这就是替换文本中$ 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()在搜索正则表达式中查找第三个匹配组,没有找到一个,并且puked.

鉴于:

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

更换

msg = msg.replaceAll("", userInput);

msg = msg.replaceAll("", Matcher.quoteReplacement(userInput));

解决了这个问题.用户可以放入任何类型的字符,包括美元符号,没有问题.它的表现完全符合您的预期.



6> Moscow Boy..:

要使用受保护的模式,您可以用"\\\\"替换所有符号,但数字和字母除外.之后,你可以在这个受保护的模式中添加你的特殊符号,使这个模式不像愚蠢的引用文本,但真的像一个模式,但你自己.没有用户特殊符号.

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");
    }
}


小错字,大后果:"([^ a-zA-z0-9])"也不匹配(即不逃避)[,\,],^你当然想要逃脱!拼写错误是第二个'z'应该是'Z',否则包括从ASCII 65到ASCII 122的所有内容
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有