6

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

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

我还将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}”更改为“eggs”等,我不确定如何执行字符串替换。有什么想法吗?提前致谢!

4

4 回答 4

6

为什么不使用 .properties 文件?这样您就可以从该文件中获取所有消息,并且可以与您的代码分开,例如(文件 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"

您可以在没有捆绑包的情况下使用 MessageFormat(是一个 java.util 库)(只需直接使用 String),但同样,捆绑包可以使您的代码清晰(并易于国际化)

于 2013-06-27T18:36:31.650 回答
4

改用这个:

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

然后,您仅获得捕获组 1 内的${和之间的内容。}

请注意,在$模式中具有特殊含义:字符串的结尾
因此必须将其转义才能被视为文字(作为大括号)。

于 2013-06-27T17:18:12.617 回答
4

更好地使用来自apache commons lang的StrSubstitutor。它也可以替代系统道具。

由于 commons-lang 3.6 StrSubstitutor 已被弃用,取而代之的是commons-text StringSubstitutor。例子:

import org.apache.commons.text.StringSubstitutor;

Properties props = new Properties();
props.setProperty("bacon", "eggs");
props.setProperty("ham", "salads");
String sampleString = "I like ${bacon} and ${ham}.";
String replaced = StringSubstitutor.replace(sampleString, props);
于 2013-10-07T06:43:48.530 回答
1

为了完成,这是一个可行的解决方案:

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();
}
于 2015-01-13T10:09:07.343 回答