【发布时间】:2010-10-31 21:03:56
【问题描述】:
我有以下模板字符串:"Hello [Name] Please find attached [Invoice Number] which is due on [Due Date]"。
我还有用于名称、发票编号和到期日的字符串变量 - 用变量替换模板中的标记的最佳方法是什么?
(请注意,如果变量恰好包含一个标记,则不应替换它)。
编辑
感谢@laginimaineb 和@alan-moore,这是我的解决方案:
public static String replaceTokens(String text,
Map<String, String> replacements) {
Pattern pattern = Pattern.compile("\\[(.+?)\\]");
Matcher matcher = pattern.matcher(text);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String replacement = replacements.get(matcher.group(1));
if (replacement != null) {
// matcher.appendReplacement(buffer, replacement);
// see comment
matcher.appendReplacement(buffer, "");
buffer.append(replacement);
}
}
matcher.appendTail(buffer);
return buffer.toString();
}
【问题讨论】:
-
不过,需要注意的一点是,StringBuffer 与刚刚同步的 StringBuilder 相同。但是,由于在此示例中您不需要同步 String 的构建,因此使用 StringBuilder 可能会更好(即使获取锁几乎是零成本的操作)。
-
不幸的是,在这种情况下你必须使用 StringBuffer;这是 appendXXX() 方法所期望的。它们从 Java 4 开始就存在了,而 StringBuilder 直到 Java 5 才被添加。不过正如你所说,这没什么大不了的,只是烦人。
-
还有一点:appendReplacement() 与 replaceXXX() 方法一样,会查找 $1、$2 等捕获组引用,并将它们替换为相关捕获组中的文本。如果您的替换文本可能包含美元符号或反斜杠(用于转义美元符号),您可能会遇到问题。处理这个问题的最简单方法是像我在上面的代码中所做的那样,将附加操作分成两个步骤。
-
艾伦 - 你发现这一点给你留下了深刻的印象。没想到这么简单的问题会这么难解决!