Groovy:动态字符串中的变量替换

19

我目前在Groovy中遇到了一个与变量替换相关的问题。尽管这相当微不足道:

Map map = [s1:"Hello", s2:"World"]
println "${map.s1} ${map.s2}!" // "Hello World!"

既然这个方法可行,我相信像这样的方法也应该是可行的:

Map map = [s1:"Hello", s2:"World"]
def dynamic = loadStringFromFile();

println "${dynamic} ${dynamic.class}" // "${s1} ${s2}! (java.lang.String)"

// now the voodoo part
println applyVoodoo(dynamic, map) // "Hello World!"

有人知道如何让这个工作吗?

谢谢

4个回答

19

通常情况下,您可以使用Groovy模板来完成这个任务。


7
dynamic.replaceAll(/\$\{(\w+)\}/) { m, k -> map[k] }

这个可行,谢谢!然而,由于我正在寻找更接近使用静态字符串的解决方案,我想出了另一个方法:def applyVoodoo(String str, Map map) { Binding b = new Binding(); for (e in map) b.setVariable(e.key, e.value); GroovyShell sh = new GroovyShell(b); return sh.evaluate(""${str}""); } - sfussenegger
关于绑定。这是一个很好的方法和非常强大的工具。请注意,您可以将地图传递给绑定构造函数(至少对于1.6.4版本)。 - Michael Easter
非常强大而优雅 - raffian

3

针对一个类似但更一般的问题,我尝试使用SimpleTemplateEngine,但发现当在您的映射中找不到占位符时,无法避免获取MissingPropertyException,这使我感到沮丧。

最终我使用了sepp2k答案的通用变体:

def s = '${s1} ${s2} $s{3}' // single quotes!
result = s.replaceAll(/\$\{(\w+)\}/) { k -> m[k[1]] ?: k[0] }
println result

这符合我的期望:

"Hello World $s{3}" 

这个方法能够运行是因为replaceAll(/group/ { k ->填充了一个数组k,第一个元素是完整匹配,第二个元素是组。所以在模式是(不包括转义字符)${(+w)}的情况下,k[0]是整个匹配:"${s1}"k[1]是组匹配:"s1"。因此,
map[k[1]] = map["s1"] = "Hello"  

如果map[k1]null,我会使用Elvis运算符?:来替换完整的未展开变量k0,例如${s3}


3
这样做就可以了:
Map map = [s1:"Hello", s2:"World"]
String dynamic = '${s1} ${s2}!' // Plain string, can be loaded from a file

// Voodoo part
GroovyShell shell = new GroovyShell(new Binding(map))
println shell.evaluate('"' + dynamic +'"')  // Hello World!

当双引号括起来的动态字符串被使用时,它会被解析为带有变量插值的GString。这意味着我们具有所有变量引用的灵活性,但没有Groovy模板的复杂性。
如果我们可以接受对变量引用进行轻微修改,那么我们甚至有更简单的选项:
Map map = [s1:"Hello", s2:"World"]
String dynamic = '${x.s1} ${x.s2}!'  // Plain string

// The voodoo part
println Eval.x(map, '"' + dynamic +'"')  // Hello World!

// This way, we can also access the map methods
dynamic = 'values: ${x.values()}'
println Eval.x(map, '"' + dynamic +'"')  // values: [Hello, World]

现在这纯粹是巫术。可悲的是,由于访问异常,我无法在团队 Jenkins 服务器上执行此操作 :( - Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接