在 groovy 中格式化字符串

Format string in groovy

我想用值

替换%s
<server>
    <id>artifactory</id>
    <username>%s</username>
    <password>%s</password>
</server>

groovy中有myString.format("name", "pass")方法吗?

groovy 基于 java 而在 java 中有 format 方法 String class

https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#format(java.lang.String,%20java.lang.Object...)

所以这应该有效

def s='''<server>
    <id>artifactory</id>
    <username>%s</username>
    <password>%s</password>
</server>'''
println String.format(s, "name", "pass")

Groovy 内置了对字符串插值的支持。您只需要使用 GString:

def name = "name"
def pass = "pass"

String formatted = """
<server>
    <id>artifactory</id>
    <username>$name</username>
    <password>$pass</password>
</server>
"""

如果您的值以数组或集合的形式出现,您甚至可以使用 params[n] 而不是命名变量 ($name),如下所示:

def params = ['name', 'pass']

String formatted = """
<server>
    <id>artifactory</id>
    <username>${params[0]}</username>
    <password>${params[1]}</password>
</server>
"""

如果你的字符串需要外化,你可以使用template engines

除此之外,您可以使用正常的 Java String.format:

def formatted = String.format(myString, "name", "pass")

您可以使用 DefaultGroovyMethods

中的 sprintf
def name = "name"
def pass = "pass"

String formatted = """
<server>
    <id>artifactory</id>
    <username>$name</username>
    <password>$pass</password>
</server>
"""
def f = sprintf( formatted, name, pass )

将上面的答案和评论收集到一个地方,有两种方法:

  1. 基于 Java String.format 功能 , which is in groovy wrapped into convenience function sprintf see e.g. here or here
  2. 基于string interpolation and more specifically this case.
  3. [edit] 正如 ernest_k 在评论中所建议的,更好的模板解决方案是 template engines。它比裸机更强大 String.format,但当然需要一些学习。

在我个人看来,第一个选项更适合最初提出的问题,因为它允许创建 "template" 字符串,然后可以在代码的任意位置与任意参数一起使用任意数量的字符串次。这似乎是原始问题中的用例。

一般来说字符串插值和sprintf有两个主要区别:

  1. 字符串插值不允许设置值的格式。
  2. 字符串插值是就地计算的,它被定义(以其正常形式),因此它不允许模板化。即使以 "special" 形式({-> expr})使用,它仍然没有明确的模板应用行为,而是依赖于具有特定名称的外部定义变量,我认为这不太可靠。

作为模板用例的示例,请考虑:

// can be defined in the same function, or as static variable in the class or even
// in other class
final String URL_TEMPLATE = 'http://fake.weather.com/rest/%s' // arg - country abbreviation

// ...

// Here we want to get weather for different countries.
def countries = ['US', 'DE', 'GB']
for (country in countries) {
    def url = URL_TEMPLATE.format(country)
    // send the request, accumulate the results
}

此解决方案使用字符串插值并不容易使用。当然,我承认,仍然可以基于字符串插值构建解决方案,但看起来会大不相同。