字符串格式中的命名占位符
在Python中,当格式化字符串时,我可以按名称而不是按位置填充占位符,就像这样:
print "There's an incorrect value '%(value)s' in column # %(column)d" % \
{ 'value': x, 'column': y }
我想知道这在Java中是否可能(希望没有外部库)?
In Python, when formatting string, I can fill placeholders by name rather than by position, like that:
print "There's an incorrect value '%(value)s' in column # %(column)d" % \
{ 'value': x, 'column': y }
I wonder if that is possible in Java (hopefully, without external libraries)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(24)
StringSubstitutor< Apache Commons Text 库中的 /code>
是实现此目的的一种轻量级方法,前提是您的值的格式已经正确。
result
字符串将包含以下内容:使用 Maven 时,您可以将此依赖项添加到
pom.xml
中:StringSubstitutor
from Apache Commons Text library is a lightweight way of doing this, provided your values are already formatted correctly.The
result
string will contain the following:When using Maven you can add this dependency to your
pom.xml
:不完全是,但您可以使用 MessageFormat 来多次引用一个值:
上述操作也可以使用 String.format() 完成,但如果您需要构建复杂的表达式,我发现 messageFormat 语法更清晰,而且您不需要关心要放入的对象的类型字符串
not quite, but you can use MessageFormat to reference one value multiple times:
The above can be done with String.format() as well, but I find messageFormat syntax cleaner if you need to build complex expressions, plus you dont need to care about the type of the object you are putting into the string
Apache Common 的另一个示例 StringSubstitutor 用于简单的命名占位符。
Another example of Apache Common StringSubstitutor for simple named placeholder.
您可以使用 StringTemplate 库,它提供您想要的以及更多。
You can use StringTemplate library, it offers what you want and much more.
例子:
Example:
感谢您的帮助!根据您的所有线索,我编写了例程来完全执行我想要的操作——使用字典进行类似 python 的字符串格式化。由于我是 Java 新手,任何提示都会受到赞赏。
Thanks for all your help! Using all your clues, I've written routine to do exactly what I want -- python-like string formatting using dictionary. Since I'm Java newbie, any hints are appreciated.
这是一个旧线程,但仅供记录,您也可以使用 Java 8 样式,如下所示:
用法:
输出将是:
This is an old thread, but just for the record, you could also use Java 8 style, like this:
Usage:
The output will be:
Apache Commons Text 的
StringSubstitutor
可以使用。 (请参阅 依赖信息 了解如何将其包含在项目中.) 请注意,StrSubstitutor
已弃用。此类支持为变量提供默认值。
要使用递归变量替换,请调用
setEnableSubstitutionInVariables(true);
。Apache Commons Text's
StringSubstitutor
can be used. (See Dependency Information for how to include it in a project.) Note thatStrSubstitutor
is deprecated.This class supports providing default values for variables.
To use recursive variable replacement, call
setEnableSubstitutionInVariables(true);
.我是一个小型库的作者,它完全可以满足您的需求:
或者您可以链接参数:
I am the author of a small library that does exactly what you want:
Or you can chain the arguments:
在撰写本文时,Java 中还没有内置任何内容。我建议您编写自己的实现。我更喜欢简单流畅的构建器界面,而不是创建映射并将其传递给函数 - 您最终会得到一个很好的连续代码块,例如:
这是一个简单的实现:
There is nothing built into Java at the moment of writing this. I would suggest writing your own implementation. My preference is for a simple fluent builder interface instead of creating a map and passing it to function -- you end up with a nice contiguous chunk of code, for example:
Here is a simple implementation:
您应该查看官方 ICU4J 库。它提供了一个 MessageFormat 类,类似于可用的类JDK,但前者支持命名占位符。
与本页提供的其他解决方案不同。 ICU4j 是由 IBM 维护并定期更新的 ICU 项目的一部分。此外,它还支持高级用例,例如多元化等。
这是一个代码示例:
You should have a look at the official ICU4J library. It provides a MessageFormat class similar to the one available with the JDK but this former supports named placeholders.
Unlike other solutions provided on this page. ICU4j is part of the ICU project that is maintained by IBM and regularly updated. In addition, it supports advanced use cases such as pluralization and much more.
Here is a code example:
Apache Commons Lang 的 replaceEach 方法可能会根据您的具体需求派上用场。您可以轻松地使用它通过以下单个方法调用按名称替换占位符:
给定一些输入文本,这会将第一个字符串数组中出现的所有占位符替换为第二个字符串数组中的相应值。
Apache Commons Lang's replaceEach method may come in handy dependeding on your specific needs. You can easily use it to replace placeholders by name with this single method call:
Given some input text, this will replace all occurrences of the placeholders in the first string array with the corresponding values in the second one.
截至 2022 年,最新的解决方案是 Apache Commons Text StringSubstitutor
来自文档:
;
As of 2022 the up-to-date solution is Apache Commons Text StringSubstitutor
From the doc:
;
如果不需要使用映射,那么您可以使用 Java 的字符串模板功能。
它在 JEP 430 中进行了描述,并作为预览功能出现在 JDK 21 中。下面是一个使用示例:
Java 的字符串模板比其他语言(例如 C# 的字符串插值和 Python 的 f 字符串)中的功能更通用,也更安全。
例如,字符串连接或插值使 SQL 注入攻击成为可能:
但此变体(来自 JEP 430)可以防止 SQL 注入:
If use of a map is not a requirement, then you can use Java's String Templates feature.
It is described in JEP 430, and it appears in JDK 21 as a preview feature. Here is an example use:
Java's string templates are more versatile, and much safer, than features in other languagues such as C#'s string interpolation and Python's f-strings.
For example, string concatenation or interpolation makes SQL injection attacks possible:
but this variant (from JEP 430) prevents SQL injection:
你可以在字符串助手类上有类似的东西
You could have something like this on a string helper class
根据答案我创建了
MapBuilder
类:然后我创建了类
StringFormat 用于字符串格式化:
您可以这样使用:
Based on the answer I created
MapBuilder
class:then I created class
StringFormat
for String formatting:which you could use like that:
我还创建了一个 util/helper 类(使用 jdk 8),它可以格式化字符串并替换变量的出现。
为此,我使用了 Matchers“appendReplacement”方法,该方法仅对格式字符串的受影响部分进行所有替换和循环。
目前,帮助程序类没有得到很好的 javadoc 文档记录。我将来会改变这一点;)
无论如何,我评论了最重要的几行(我希望如此)。
您可以为具有值(或后缀前缀或 noKeyFunction)的特定 Map 创建类实例
喜欢:
此外,您还可以定义如果值映射中的键丢失会发生什么(两种方式都有效,例如格式字符串中的变量名称错误或映射中缺少键)。
默认行为是抛出未经检查的异常(未经检查,因为我使用默认的 jdk8 函数,它无法处理检查的异常),例如:
您可以在构造函数调用中定义自定义行为,例如:
或将其委托回默认的无键行为:
为了更好地处理,还有静态方法表示,例如:
I created also a util/helper class (using jdk 8) which can format a string an replaces occurrences of variables.
For this purpose I used the Matchers "appendReplacement" method which does all the substitution and loops only over the affected parts of a format string.
The helper class isn't currently well javadoc documented. I will changes this in the future ;)
Anyway I commented the most important lines (I hope).
You can create a class instance for a specific Map with values (or suffix prefix or noKeyFunction)
like:
Further more you can define what happens if a key in the values Map is missing (works in both ways e.g. wrong variable name in format string or missing key in Map).
The default behavior is an thrown unchecked exception (unchecked because I use the default jdk8 Function which cant handle checked exceptions) like:
You can define a custom behavior in the constructor call like:
or delegate it back to the default no key behavior:
For better handling there are also static method representations like:
有 Java 插件可以在 Java 中使用字符串插值(如 Kotlin、JavaScript)。支持 Java 8、9、10、11… https://github.com/antkorwin/better-strings< /a>
在字符串文字中使用变量:
使用表达式:
使用函数:
有关详细信息,请阅读项目自述文件。
There is Java Plugin to use string interpolation in Java (like in Kotlin, JavaScript). Supports Java 8, 9, 10, 11… https://github.com/antkorwin/better-strings
Using variables in string literals:
Using expressions:
Using functions:
For more info, please read the project README.
不幸的是,快速回答是否定的。但是,您可以非常接近合理的语法:
至少它比
String.format
更具可读性和可预测性!The quick answer is no, unfortunately. However, you can come pretty close to a reasonable syntaks:
It's more readable and predictable than
String.format
, at least!我的答案是:
a)尽可能使用 StringBuilder
b)保留“占位符”的位置(以任何形式:整数是最好的,特殊字符如美元宏等),然后使用 StringBuilder.insert() (参数的几个版本)。
使用外部库似乎有点矫枉过正,我相信当 StringBuilder 在内部转换为 String 时,性能会显着降低。
My answer is to:
a) use StringBuilder when possible
b) keep (in any form: integer is the best, speciall char like dollar macro etc) position of "placeholder" and then use
StringBuilder.insert()
(few versions of arguments).Using external libraries seems overkill and I belive degrade performance significant, when StringBuilder is converted to String internally.
我尝试了一种快速的方法
I tried in just a quick way
我最终得到了下一个解决方案:
使用方法
substitute()
创建类TemplateSubstitutor
并使用它来格式化输出然后创建一个字符串模板并用值填充它
I ended up with the next solution:
Create class
TemplateSubstitutor
with methodsubstitute()
and use it to format outputThen create a string template and fill it with values
尝试 Freemarker,模板库。
Try Freemarker, templating library.
https://dzone.com/articles/java-string-format-examples String.format(inputString, [listOfParams]) 将是最简单的方法。字符串中的占位符可以按顺序定义。有关更多详细信息,请查看提供的链接。
https://dzone.com/articles/java-string-format-examples String.format(inputString, [listOfParams]) would be the easiest way. Placeholders in string can be defined by order. For more details check the provided link.