在Python中,格式化字符串时,我可以按名称而不是按位置填充占位符,如下所示:
print "There's an incorrect value '%(value)s' in column # %(column)d" % \
{ 'value': x, 'column': y }
我想知道这在Java中是否可能(希望没有外部库)?
在Python中,格式化字符串时,我可以按名称而不是按位置填充占位符,如下所示:
print "There's an incorrect value '%(value)s' in column # %(column)d" % \
{ 'value': x, 'column': y }
我想知道这在Java中是否可能(希望没有外部库)?
当前回答
可以使用Apache Commons StringSubstitutor。注意,StrSubstitutor已弃用。
import org.apache.commons.text.StringSubstitutor;
// ...
Map<String, String> values = new HashMap<>();
values.put("animal", "quick brown fox");
values.put("target", "lazy dog");
StringSubstitutor sub = new StringSubstitutor(values);
String result = sub.replace("The ${animal} jumped over the ${target}.");
// "The quick brown fox jumped over the lazy dog."
这个类支持为变量提供默认值。
String result = sub.replace("The number is ${undefined.property:-42}.");
// "The number is 42."
要使用递归变量替换,调用setEnableSubstitutionInVariables(true);。
Map<String, String> values = new HashMap<>();
values.put("b", "c");
values.put("ac", "Test");
StringSubstitutor sub = new StringSubstitutor(values);
sub.setEnableSubstitutionInVariables(true);
String result = sub.replace("${a${b}}");
// "Test"
其他回答
我是一个小型库的作者,它可以做你想要的:
Student student = new Student("Andrei", 30, "Male");
String studStr = template("#{id}\tName: #{st.getName}, Age: #{st.getAge}, Gender: #{st.getGender}")
.arg("id", 10)
.arg("st", student)
.format();
System.out.println(studStr);
或者你可以串起参数:
String result = template("#{x} + #{y} = #{z}")
.args("x", 5, "y", 10, "z", 15)
.format();
System.out.println(result);
// Output: "5 + 10 = 15"
你可以在字符串助手类上有这样的东西
/**
* An interpreter for strings with named placeholders.
*
* For example given the string "hello %(myName)" and the map <code>
* <p>Map<String, Object> map = new HashMap<String, Object>();</p>
* <p>map.put("myName", "world");</p>
* </code>
*
* the call {@code format("hello %(myName)", map)} returns "hello world"
*
* It replaces every occurrence of a named placeholder with its given value
* in the map. If there is a named place holder which is not found in the
* map then the string will retain that placeholder. Likewise, if there is
* an entry in the map that does not have its respective placeholder, it is
* ignored.
*
* @param str
* string to format
* @param values
* to replace
* @return formatted string
*/
public static String format(String str, Map<String, Object> values) {
StringBuilder builder = new StringBuilder(str);
for (Entry<String, Object> entry : values.entrySet()) {
int start;
String pattern = "%(" + entry.getKey() + ")";
String value = entry.getValue().toString();
// Replace every occurence of %(key) with value
while ((start = builder.indexOf(pattern)) != -1) {
builder.replace(start, start + pattern.length(), value);
}
}
return builder.toString();
}
另一个Apache Common StringSubstitutor的简单命名占位符的例子。
String template = "Welcome to {theWorld}. My name is {myName}.";
Map<String, String> values = new HashMap<>();
values.put("theWorld", "Stackoverflow");
values.put("myName", "Thanos");
String message = StringSubstitutor.replace(template, values, "{", "}");
System.out.println(message);
// Welcome to Stackoverflow. My name is Thanos.
public static String format(String format, Map<String, Object> values) {
StringBuilder formatter = new StringBuilder(format);
List<Object> valueList = new ArrayList<Object>();
Matcher matcher = Pattern.compile("\\$\\{(\\w+)}").matcher(format);
while (matcher.find()) {
String key = matcher.group(1);
String formatKey = String.format("${%s}", key);
int index = formatter.indexOf(formatKey);
if (index != -1) {
formatter.replace(index, index + formatKey.length(), "%s");
valueList.add(values.get(key));
}
}
return String.format(formatter.toString(), valueList.toArray());
}
例子:
String format = "My name is ${1}. ${0} ${1}.";
Map<String, Object> values = new HashMap<String, Object>();
values.put("0", "James");
values.put("1", "Bond");
System.out.println(format(format, values)); // My name is Bond. James Bond.
您应该看看官方的ICU4J库。它提供了一个类似于JDK的MessageFormat类,但前者支持命名占位符。
与本页提供的其他解决方案不同。ICU4j是ICU项目的一部分,由IBM维护并定期更新。此外,它还支持高级用例,如多元化等。
下面是一个代码示例:
MessageFormat messageFormat =
new MessageFormat("Publication written by {author}.");
Map<String, String> args = Map.of("author", "John Doe");
System.out.println(messageFormat.format(args));