【发布时间】:2020-09-14 06:04:36
【问题描述】:
大部分情况下我们用正则表达式替换字符串段,当替换的文本是一个变量,所以基本上程序员是不知道的。
但是我们总是忘记,java matcher.replaceAll() 的行为将非常依赖于替换本身。因此,替换不应包含任何 '$' 或 '\' 字符,以提供 naive 结果。
例如以下代码抛出“java.lang.IndexOutOfBoundsException: No group 2”,以防变量薪水等于“$2”。
String salary = "$2";
Pattern p = Pattern.compile("SAL");
Matcher m = p.matcher("Salary: SAL");
String s = m.replaceAll(salary);
System.out.println(s);
我知道,如果“$”符号用“\”转义,那么我们将得到预期的结果。但话又说回来,'\' 也应该用 '\' 转义。所以正确的解决方案是:
String salary = "$2";
Pattern p = Pattern.compile("SAL");
Matcher m = p.matcher("Salary: SAL");
String s = m.replaceAll(salary.replace("\\", "\\\\").replace("$", "\\$"));
System.out.println(s);
首先,这使用起来不太方便,而且在性能方面也不是很好。 (对于 appendReplacement() 方法也是如此。)
那么你能推荐一些更通用的解决方案吗?
【问题讨论】:
-
'有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。'
-
您所说的“性能不太好”是什么意思?你的意思是你不喜欢两个
replace调用必须循环遍历字符串两次?编写自己的escapeReplacement方法,使用StringBuilder并且只循环字符串一次怎么样? -
性能方面:我通过两个方法调用引入了转义字符,然后 Matcher 将搜索我的转义符以将它们替换回来。 不太好:正则表达式已经很昂贵了,所以这个额外的钩子可能不会影响整体性能。
标签: java replace escaping matcher metacharacters