web-dev-qa-db-ja.com

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

誰かがこれを機能させる方法を知っていますか?

乾杯

17
sfussenegger

通常、これは Groovy Templates で行います。

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

これはそれをします:

Map map = [s1:"Hello", s2:"World"]
String dynamic = '${s1} ${s2}!' // Plain string, can be loaded from a file

// Voodoo part
GroovyShell Shell = new GroovyShell(new Binding(map))
println Shell.evaluate('"' + dynamic +'"')  // Hello World!

dynamic文字列が二重引用符で囲まれている場合、変数補間を使用してGStringと評価されます。つまり、Groovyテンプレートを複雑にすることなく、変数参照の柔軟性をすべて備えています。

変数参照のわずかな変更を受け入れることができる場合は、さらに簡単なオプションがあります。

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

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

// This way, we can also access the map methods
dynamic = 'values: ${x.values()}'
println Eval.x(map, '"' + dynamic +'"')  // values: [Hello, World]
3
Ari Manninen

同様の、しかしより一般的な問題については、SimpleTemplateEngineを使用してみましたが、マップにプレースホルダーが見つからない場合は常にMissingPropertyExceptionが発生するのを避けられないという点でイライラしました。私はsepp2kの答えのこの一般化されたバリエーションを使用することになりました:

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

これは[〜#〜] i [〜#〜]欲しかったものを与えます:

_"Hello World $s{3}" 
_

これは、_replaceAll(/group/ { k ->_がkを配列で埋めるために機能します。最初の要素は完全一致で、2番目の要素はグループです。したがって、パターンが(sans escape chars)${(+w)}の場合、_k[0]_は完全一致です:_"${s1}"_および_k[1]_グループ一致_"s1"_ 、 そう

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

_map[k1]_がnullの場合、elvis _?:_を使用して、_k0_のような非拡張変数である完全な_${s3}_をサブインします。

2
Rhubarb