2009-09-24 14 views
12

Mam obecnie do czynienia z problemem zmiennego substytucyjnego w groovy. Choć jest to dość banalne:Groovy: Zastępowanie zmiennych w dynamicznych ciągach znaków

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

Jak to działa, jestem pewna, że ​​coś jak to powinno działać, a także:

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

Czy ktoś wie jak zdobyć tej pracy?

Cheers

Odpowiedz

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

To działa, dziękuję! Jednakże, jak szukałem czegoś, co jest bliżej za pomocą strun statyczne, wpadłem na inne rozwiązanie: def applyVoodoo (String str, mapa mapa) { \t Oprawa b = new Binding(); \t dla (e na mapie) b.setVariable (e.key, e.value); \t GroovyShell sh = new GroovyShell (b); \t return sh.evaluate ("\" $ {str} \ ""); } – sfussenegger

+0

re: Binding. To dobre podejście i bardzo potężne narzędzie. Zwróć uwagę, że możesz przekazać mapę do konstruktora Binding (przynajmniej dla wersji 1.6.4). –

+0

niesamowicie potężny i elegancki – raffian

1

Dla podobnego, ale bardziej ogólnego problemu, próbowałem używać SimpleTemplateEngine, ale stwierdziłem, że jest to frustrujące, ponieważ nie można uniknąć generowania MissingPropertyException za każdym razem, gdy na mapie nie ma symbolu zastępczego. skończyło się korzystania z tej uogólnionej wariancji sepp2k za odpowiedź:

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

co daje co I chciał:

"Hello World $s{3}" 

to działa, ponieważ replaceAll(/group/ { k -> wypełnia k z tablicy: pierwszy element jest pełny mecz, a drugi to grupa. Więc w moim przypadku, gdy wzór (sans uciec znaków) ${(+w)} następnie k[0] jest cały mecz: "${s1}" i k[1] mecz grupa "s1", więc

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

a jeśli map[k1] jest null używam Elvisa ?: sub w pełny k0 która jest zmienna un-rozszerzony, jak ${s3}

2

Jeśli możemy zaakceptować lekką modyfikację w referencji zmiennych, zrobiłbym to tak:

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! 

Wyrażenie "${x.s1} ${x.s2}!" ocenia się na GString z interpolacją zmiennej. Oznacza to, że mamy większą elastyczność dzięki referencjom zmiennych, bez złożoności szablonów Groovy.

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