题
Java 是否有内置方法来转义任意文本,以便将其包含在正则表达式中?例如,如果我的用户输入“$5”,我希望完全匹配它,而不是输入结束后的“5”。
解决方案
自从 Java 1.5,是的:
Pattern.quote("$5");
其他提示
之间的区别 Pattern.quote
和 Matcher.quoteReplacement
在看到下面的例子之前我并不清楚
s.replaceFirst(Pattern.quote("text to replace"),
Matcher.quoteReplacement("replacement text"));
可能来不及回复,但您也可以使用 Pattern.LITERAL
, ,这将在格式化时忽略所有特殊字符:
Pattern.compile(textToFormat, Pattern.LITERAL);
我想你所追求的是 \Q$5\E
. 。另请参阅 Pattern.quote(s)
Java5中引入。
看 图案 javadoc 了解详细信息。
首先,如果
- 你使用replaceAll()
- 你不使用 Matcher.quoteReplacement()
- 要替换的文本包括 $1
它不会在末尾添加 1。它将查看第一个匹配组和子组的搜索正则表达式。这就是替换文本中 $1、$2 或 $3 的含义:匹配搜索模式中的组。
我经常将长文本字符串插入 .properties 文件,然后从中生成电子邮件主题和正文。事实上,这似乎是 Spring 框架中执行 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));
解决了问题。用户可以毫无问题地输入任何类型的字符,包括美元符号。它的行为完全符合您的预期。
要获得受保护的模式,您可以将所有符号替换为“\\\\”,数字和字母除外。之后,您可以在受保护的模式中放入您的特殊符号,以使该模式不像愚蠢的引用文本那样工作,而是真正像模式一样,而是您自己的。没有用户特殊符号。
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");
}
}
Pattern.quote("blabla") 效果很好。
Pattern.quote() 工作得很好。它用字符“\问“ 和 ”\E”,并且如果它确实转义了“\Q”和“\E”。但是,如果您需要进行真正的正则表达式转义(或自定义转义),您可以使用以下代码:
String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
该方法返回: 一些/\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"));