2009-09-24 13 views
12

Attualmente sto affrontando un problema correlato di sostituzione variabile in groovy. Mentre questo è abbastanza banale:Groovy: sostituzione variabile in stringhe dinamiche

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

Come questo funziona, sono abbastanza sicuro che qualcosa di simile dovrebbe funzionare così:

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

Qualcuno sa come ottenere questo lavoro?

Acclamazioni

risposta

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

Funziona, grazie! Tuttavia, come ero alla ricerca di qualcosa che è più vicino al utilizzando stringhe statiche, mi si avvicinò con un'altra soluzione: def applyVoodoo (String str, Mappa mappa) { \t Binding b = new Binding(); \t per (e in mappa) b.setVariable (e.key, e.value); \t GroovyShell sh = new GroovyShell (b); \t return sh.evaluate ("\" $ {str} \ ""); } – sfussenegger

+0

re: associazione. Questo è un buon approccio e uno strumento molto potente. Si noti che è possibile passare la mappa al costruttore Binding (almeno per la versione 1.6.4). –

+0

incredibilmente potente ed elegante – raffian

1

Per un problema simile ma più generale, ho provato a utilizzare SimpleTemplateEngine, ma ho trovato frustrante il fatto che non è possibile evitare MissingPropertyException ogni volta che un segnaposto non viene trovato nella mappa. Ho finito per usare questa variazione generalizzata della risposta di sepp2k:

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

che dà quello I voluto:

"Hello World $s{3}" 

Il questo funziona perché il replaceAll(/group/ { k -> riempie k con una serie: il primo elemento è la partita completa e la 2a è il gruppo. Quindi, nel mio caso in cui il modello è (sans fuga caratteri) ${(+w)} poi k[0] è tutta la partita: "${s1}" e k[1] il match gruppo "s1", così

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

e se map[k1] è null Io uso Elvis ?: al sub nel piena k0 che è la variabile non-espansa, come ${s3}

2

Se possiamo accettare leggera modifica sui riferimenti variabili, lo farei in questo modo:

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! 

Expression "${x.s1} ${x.s2}!" restituisce GString con interpolazione variabile. Ciò significa che abbiamo più flessibilità con i riferimenti variabili, senza la complessità di Groovy Templates.

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