在Java字符串中搜索并替换格式化的属性

时间:2013-06-27 17:13:47

标签: java regex string

我将获得包含格式化“属性”的字符串;也就是说,Strings封装在标准的“$ {”和“}”标记内:

  

“这是$ {string}的$ {example},我可能是$ {given}。”

我还将为每个可能的格式化属性添加HashMap<String,String>替换:

HashMap Keys           HashMapValues
===========================================
bacon                  eggs
ham                    salads

这样,给定以下字符串:

  

“我喜欢吃$ {bacon}和$ {ham}。”

我可以将它发送到Java方法,将其转换为:

  

“我喜欢吃鸡蛋和沙拉。”

这是我最好的尝试:

System.out.println("Starting...");

String regex = "$\\{*\\}";
Map<String,String> map = new HashMap<String, String>();
map.put("bacon", "eggs");
map.put("ham", "salads");

String sampleString = "I like ${bacon} and ${ham}.";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sampleString);
while(matcher.find()) {
    System.out.println("Found " + matcher.group());

    // Strip leading "${" and trailing "}" off.
    String property = matcher.group();

    if(property.startsWith("${"))
        property = property.substring(2);
    if(property.endsWith("}"))
        property = property.substring(0, property.length() - 1);

    System.out.println("Before being replaced, property is: " + property);

    if(map.containsKey(property))
        property = map.get(property);

    // Now, not sure how to locate the original property ("${bacon}", etc.)
    // inside the sampleString so that I can replace "${bacon}" with
    // "eggs".
}

System.out.println("Ending...");

当我执行此操作时,我没有错误,只是看到“正在开始...”和“结束...”输出。这告诉我我的正则表达式不正确,因此Matcher无法匹配任何属性。

所以我的第一个问题是:这个正则表达式应该是什么?

一旦我过去了,我不知道如果我将“$ {bacon}”更改为“鸡蛋”等,如何执行字符串替换等等。任何想法?提前谢谢!

4 个答案:

答案 0 :(得分:6)

为什么不使用.properties文件?这样你可以从该文件获取所有消息,并且可以与你的代码分开,例如(file example.properties):

message1=This is a {0} with format markers on it {1}

然后在你的课程中加载你的包并像这样使用它:

ResourceBundle bundle = ResourceBundle.getBundle("example.properties", Locale.getDefault());
MessageFormat.format(bundle.getString('message1'), "param0", "param1"); // This gonna be your formatted String "This is a param0 with format markers on it param1"

你可以使用没有bundle的MessageFormat(是一个java.util库)(只是直接使用String),但是再次使用bundle会使你的代码变得清晰(并且易于国际化)

答案 1 :(得分:4)

请改用:

String regex = "\\$\\{([^}]*)\\}";

然后,您只获取捕获组1内的${}之间的内容。

请注意$在模式中有特殊含义:字符串的结尾
因此,它必须被转义为字面意义(如大括号)。

答案 2 :(得分:2)

最好从apache commons lang使用StrSubstitutor。它也可以替代System props

答案 3 :(得分:0)

完成后,这是一个有效的解决方案:

static final Pattern EXPRESSION_PATTERN = Pattern.compile("\\$\\{([^}]*)\\}");

/**
 * Replace ${properties} in an expression
 * @param expression expression string
 * @param properties property map
 * @return resolved expression string
 */
static String resolveExpression(String expression, Map<String, String> properties) {
    StringBuilder result = new StringBuilder(expression.length());
    int i = 0;
    Matcher matcher = EXPRESSION_PATTERN.matcher(expression);
    while(matcher.find()) {
        // Strip leading "${" and trailing "}" off.
        result.append(expression.substring(i, matcher.start()));
        String property = matcher.group();
        property = property.substring(2, property.length() - 1);
        if(properties.containsKey(property)) {
            //look up property and replace
            property = properties.get(property);
        } else {
            //property not found, don't replace
            property = matcher.group();
        }
        result.append(property);
        i = matcher.end();
    }
    result.append(expression.substring(i));
    return result.toString();
}