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

时间:2009-09-24 15:30:24

标签: groovy templates

我目前正面临着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 个答案:

答案 0 :(得分:12)

您通常会使用Groovy Templates执行此操作。

答案 1 :(得分:7)

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

答案 2 :(得分:3)

如果我们可以接受对变量引用的轻微修改,我会这样做:

Map map = [s1:"Hello", s2:"World"]
def dynamic = '${x.s1} ${x.s2}!'  // Plain string
println "${dynamic} ${dynamic.class}" // "${x.s1} ${x.s2}! class java.lang.String"

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

表达式"${x.s1} ${x.s2}!"使用变量插值求值为GString。这意味着,我们可以更灵活地使用变量引用,而不会出现Groovy模板的复杂性。

dynamic = 'keys: ${x.values()}'
println Eval.x(map, '"' + dynamic +'"')  // keys: [Hello, World]

答案 3 :(得分:2)

对于类似但更普遍的问题,我尝试使用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}