2009-09-24 3 views
12

В настоящее время я сталкиваюсь с проблемой с переменной заменой в groovy. Хотя это довольно тривиально: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!" 

Кто-нибудь знает, как получить эту работу?

Приветствия

ответ

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

Это работает, спасибо! Однако, как я искал что-то, что находится ближе к использованию статических строк, я придумал другое решение: Защиту applyVoodoo (String ул, Карта Карта) { \t Binding б = новый Binding(); \t для (e на карте) b.setVariable (e.key, e.value); \t GroovyShell sh = new GroovyShell (b); \t return sh.evaluate ("\" $ {str} \ ""); } – sfussenegger

+0

re: Binding. Это хороший подход и очень мощный инструмент. Обратите внимание, что вы можете передать карту в конструктор Binding (по крайней мере на 1,6.4). –

+0

невероятно мощный и элегантный – raffian

1

Для подобной, но более общей проблемы, я попытался использовать 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 я использую Элвис ?: к югу в полный k0, который является не-вычисляемой переменной, как ${s3}

2

Если мы можем принять небольшую модификацию на переменных ссылок, я хотел бы сделать это следующим образом:

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] 
Смежные вопросы