此java lambda替换以$(
开头并以)
结尾的Map
预定义值的字符串:
SortedMap<String, String> map = new TreeMap<String, String>();
map.put("test", "REPLACE");
String update = Arrays.stream("$(test) (test) (test2)".split("\\(\\$|\\)"))
.map(token -> map.getOrDefault(token, token))
.collect(Collectors.joining(""));
System.out.println(update);
这会打印REPLACE (test (test2
这几乎按预期工作,但右括号已从(test
&amp; (test2
。我是否需要更新正则表达式,或者可以修改lambda以生成:
REPLACE (test) (test2)
答案 0 :(得分:1)
问题是您匹配可能不匹配的$(
和)
。您只需要在)
后跟$(
和$(
后跟)
匹配。
Matcher#appendReplacementCallback
您可以使用简单的正则表达式来匹配$(...)
字符串并捕获其中的文本以从地图中获取令牌,并在旅途中执行替换&#34;&#34;匹配时:
SortedMap<String, String> map = new TreeMap<String, String>();
map.put("test", "REPLACE");
String update = "$(test) (test) (test2)";
Matcher m = Pattern.compile("\\$\\(([^)]*)\\)").matcher(update);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, map.getOrDefault(m.group(1), m.group(1)));
}
m.appendTail(sb);
System.out.println(sb);
请参阅IDEONE demo
Split
和Lookarounds 免责声明: 此方法仅适用于不那么长的字符串 。
您也可以使用外观。随着前瞻,没有问题,它是无限宽度。使用lookbehind,我们可以依赖受约束的宽度lookbehind(使用限制量词而不是+
或*
):
SortedMap<String, String> map = new TreeMap<String, String>();
map.put("test", "REPLACE");
String update = Arrays.stream("$(test) (test) (test2)"
.split("\\$\\((?=[^)]*\\))|(?<=\\$\\([^(]{0,1000})\\)"))
.map(token -> map.getOrDefault(token, token))
.collect(Collectors.joining(""));
System.out.println(update); // => REPLACE (test) (test2)
请参阅IDEONE demo
正则表达式现在写着:
\$\((?=[^)]*\))
- 匹配$(
后面跟着)
以外的0 +字符,然后是)
|
- 或(?<=\$\([^(]{0,1000})\)
- 匹配前面带有)
的{{1}}以外的0-1000(应该足够)字符的(
。答案 1 :(得分:1)
您可以使用地图keySet
public static String replaceKeywords(
final String template,
final Map<String, String> map
) {
return map.keySet().stream().reduce(template,
(acc, key) -> acc.replaceAll("\\$\\(" + key + "\\)", map.get(key)));
}
用法:
Map<String, String> map = new TreeMap<String, String>();
map.put("test", "FOO");
map.put("test2", "BAR");
System.out.println(replaceKeywords("$(test) $(test2) (test2)", map));
输出:
FOO BAR (test2)