我正在尝试生成HashMap对象,该对象具有从解析的文本输入中设置的属性和值。在简单分配的情况下可以正常工作,但希望使其更聪明并使用注入。
apt_install_from_file() {
declare -r FILE_PATH="$1" # packages
regex["deb"]='deb "(.*)" \[args: "(.*)", "(.*)", "(.*)"\]'
if [ -e "$FILE_PATH" ]; then
cat < "$FILE_PATH" | while read -r LINE; do
if [[ $LINE =~ ${regex[deb]} ]]; then
# ...
fi
done
fi
}
产生预期的输出:
def result = new HashMap();
def buildLog = """
BuildDir:
MSBuildProjectFile:test.csproj
TargetName: test
Compile:
Reference:
""".trim().readLines()*.trim()
buildLog.each {
def (k,v) = it.tokenize(':')
result."${k.trim()}"=v?.trim()
}
println "\nResult:\n${result.collect { k,v -> "\t$k='$v'\n" }.join()}"
用注入替换.each {}闭包的内部之后:
Result:
Reference='null'
MSBuildProjectFile='test.csproj'
BuildDir='null'
TargetName='test'
Compile='null'
生成的结果缺少未设置的值
it.tokenize(':').inject({ key, value -> result."${key}" = value?.trim()})
我做错了什么,尝试使用inject(“”,{...}),但似乎将may键推入了值。
答案 0 :(得分:2)
inject
基本上是 reduce 。约简函数采用两个参数,即上一次迭代的结果或初始值(例如累加器)以及序列中的下一个值。这样就可以了,但是由于您只期望一个序列值,所以它只会使代码复杂。
我在这里确实看到了collectEntries的一个很好的用途,因为它允许您使用小的键/值映射或两个元素的列表来创建Map。而后者有:
result = buildLog.collectEntries {
it.split(":",2)*.trim()
}
应该为您的代码而不是buildLog.each
工作