2009-09-24 15 views
12

Actualmente estoy enfrentando un problema relacionado con la sustitución variable en groovy. Si bien esto es bastante trivial:Groovy: Sustitución variable en cadenas dinámicas

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

Como funciona esto, estoy bastante seguro de que algo como esto debería funcionar así:

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!" 

¿Alguien sabe cómo conseguir este trabajo?

Saludos

Respuesta

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

Esto funciona, gracias! Sin embargo, como yo estaba buscando algo que está más cerca a la utilización de cadenas estáticas, se me ocurrió otra solución: applyVoodoo def (String str, mapa mapa) { \t Encuadernación b = new Binding(); \t para (e en el mapa) b.setVariable (e.key, e.value); \t GroovyShell sh = new GroovyShell (b); \t return sh.evaluate ("\" $ {str} \ ""); } – sfussenegger

+0

re: Encuadernación. Este es un buen enfoque y una herramienta muy poderosa. Tenga en cuenta que puede pasar el mapa al constructor Binding (para 1.6.4 al menos). –

+0

increíblemente poderoso y elegante – raffian

1

Para un problema similar pero más general, traté de usar SimpleTemplateEngine, pero me pareció frustrante porque no se puede evitar obtener MissingPropertyException cada vez que no se encuentra un marcador de posición en el mapa. Terminé usando esta variación generalizada de la respuesta de sepp2k:

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

el que da lo I querían:

"Hello World $s{3}" 

El que esto funciona porque el replaceAll(/group/ { k -> llena k con una matriz: el primer elemento es el partido completo, y el 2do es el grupo. Así que en mi caso en el que el patrón es (sans escapan caracteres) ${(+w)} continuación k[0] es todo el partido: "${s1}" y k[1] el partido del grupo "s1", por lo

map[k[1]] = map["s1"] = "Hello" 

y si map[k1] es null utilizo Elvis ?: a sub en el k0 completa que es la variable no expandido, como ${s3}

2

Si podemos aceptar una ligera modificación en las referencias a variables, lo haría así:

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! 

Expresión "${x.s1} ${x.s2}!" evalúa a GString con interpolación variable. Esto significa que tenemos más flexibilidad con las referencias de variables, sin la complejidad de las plantillas de Groovy.

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