首页 > 解决方案 > Java字符串用评估的键替换正则表达式模式

问题描述

我有一个这样的输入字符串

I want to go to {places} where {things} are happening.

{places} 和 {things} 的值是惰性计算的(即首先我找出所有需要替换的键,然后计算它们的值,然后在原始字符串中替换它们)。

我可以使用以下代码找出所有密钥并删除它们。

public class Temp {
    private static final Pattern betweenCurlyBracesMatcher = Pattern.compile("\\{(.*?)\\}");

    public static void main(String args[]) {
        System.out.println(resolve2("hello {world} from {here}"));
    }

    public static String resolve2(String input) {
        Map<String, String> keyValueMap = new HashMap<>();
        Matcher matcher = betweenCurlyBracesMatcher.matcher(input);
        while (matcher.find()) {
            String key = matcher.group(1);
            if (!keyValueMap.containsKey(key)) {
                keyValueMap.put(key, computeValueForKey(key));
            }
        }
        for (Map.Entry<String, String> entry : keyValueMap.entrySet()) {
            input = input.replace("{" + entry.getKey() + "}", entry.getValue());  // << ugly code here
        }
        return input;
    }

    private static String computeValueForKey(String key) {
        return "new" + key;
    }
}

但我不满意

input = input.replace("{" + entry.getKey() + "}", entry.getValue());

因为这意味着每当我更改我的正则表达式时,我都必须更新这个逻辑。这个问题有没有更优雅的解决方案。


从 {这里}输入你好 {world}

从无处输出你好新世界


输入我想去 {things} 正在发生的 {places}。

输出我想去发生新事物的新地方。

标签: javaregex

解决方案


您应该在这里使用Matcher#appendReplacementMatcher#appendTailAPI:

Map<String, String> keyValueMap = new HashMap<>();
keyValueMap.put("places", "to America");
keyValueMap.put("things", "events");
String input = "I want to go to {places} where {things} are happening.";
Pattern pattern = Pattern.compile("\\{(.*?)\\}");
Matcher matcher = pattern.matcher(input);
StringBuffer buffer = new StringBuffer();

while(matcher.find()) {
    matcher.appendReplacement(buffer, keyValueMap.get(matcher.group(1)));
}
matcher.appendTail(buffer);
System.out.println(buffer.toString());

这打印:

I want to go to to America where events are happening.

推荐阅读