我有一个与此类似的字符串哈希:
Map map = ['a.b.c': 'Hi']
...我需要在gradle中使用以扩展这样的表达式:
This is a greeting: ${a.b.c}
如果我使用展开的gradle复制任务,我将收到一条错误消息'No such property:a'。
有没有办法让gradle / groovy将该地图转换为我需要解析的属性?
答案 0 :(得分:2)
我找不到内置的答案,但它是一个完整的,自包含的方法,可以在Map上用作元方法来做你想要的:
Map map = ['a.b.c': 'Hi', 'a.b.d': 'Yo', 'f.g.h': 'Howdy']
Map.metaClass.expandKeys = { separator = '.' ->
def mergeMaps = { a, b ->
b.each{ k, v ->
if(a[k] && (v instanceof Map)) {
mergeMaps(a[k], v)
} else {
a[k] = v
}
}
a
}
delegate.inject([:]){ result, k, v ->
mergeMaps(result, k.tokenize(separator).reverse().inject(v){last, subkey -> [(subkey):last] })
}
}
assert map.expandKeys() == [a:[b:[c:"Hi", d:"Yo"]], f:[g:[h:"Howdy"]]]
它还允许使用与.
不同的分隔符,只需将分隔符传递到expandKeys
方法
如果你想像普通函数一样使用它,那么你可以这样做:
Map map = ['a.b.c': 'Hi', 'a.b.d': 'Yo', 'f.g.h': 'Howdy']
def expandKeys = { Map input, separator = '.' ->
def mergeMaps = { a, b ->
b.each{ k, v ->
if(a[k] && (v instanceof Map)) {
mergeMaps(a[k], v)
} else {
a[k] = v
}
}
a
}
input.inject([:]){ result, k, v ->
mergeMaps(result, k.tokenize(separator).reverse().inject(v){last, subkey -> [(subkey):last] })
}
}
assert expandKeys(map) == [a:[b:[c:"Hi", d:"Yo"]], f:[g:[h:"Howdy"]]]
除了合并地图之外,主要技巧是拆分然后反转每个键。然后可以向后构建最终层次结构。此外,可能有更好的方法来处理合并,因为我不喜欢最后挂a
。
答案 1 :(得分:1)
我对Gradle一无所知,但也许这会有所帮助......
如果您有地图
Map map = ['a.b.c': 'Hi']
然后您无法使用
检索值“Hi”map.a.b.c
相反,您必须使用:
map.'a.b.c'
或
map['a.b.c']
答案 2 :(得分:0)
我不确定您的需求是什么,但是如果您只需要替换类似属性的令牌并且不需要Groovy模板的全部功能,那么filter()
方法与Ant的ReplaceTokens
方法相结合1}}类比expand()
更安全(也更快)。请参阅Gradle用户指南中的Filtering files。