我试图从docker inspect
的JSON输出中解析环境变量。令人讨厌的是,这些环境变量不作为有用的键值对返回。它们只是一个x = y字符串的数组。这是输出的相关片段:
[
{
"Config": {
"Env": [
"JENKINS_HOST=1.2.3.4",
"JENKINS_INSTANCE=tea",
"JENKINS_NAME=Enterprise Architecture Tools",
"JENKINS_VERSION=2.46.2",
"JENKINS_PROTOCOL=http"
]
}
}
]
我想把这个数组转换成这样的东西:
{
"Config": {
"Env": {
"JENKINS_HOST": "1.2.3.4",
"JENKINS_INSTANCE": "tea",
"JENKINS_NAME": "Enterprise Architecture Tools",
"JENKINS_VERSION": "2.46.2",
"JENKINS_PROTOCOL": "http"
}
}
}
这样,我可以使用像jq '.[] | .Config.Env.JENKINS_HOST'
这样的命令来获取我关心的值。我无法弄清楚如何实现这一目标。
选择数据相对容易,甚至将键和值拆分为单独的元素。例如,如果我使用jq '.[] | .Config.Env | .[] | split("=")'
,我会得到这样的数据:
[
"JENKINS_HOST",
"1.2.3.4"
]
[
"JENKINS_INSTANCE",
"tea"
]
[
"JENKINS_NAME",
"Enterprise Architecture Tools"
]
[
"JENKINS_VERSION",
"2.46.2"
]
[
"JENKINS_PROTOCOL",
"http"
]
但是,我无法弄清楚如何将该数据转换为对象分配。它似乎应该是map
或reduce
的某种组合,但我很难过。有人能指出我正确的方向吗?
答案 0 :(得分:8)
要将两个字符串的数组(例如[" k"," v"])转换为对象,您可以写:
{ (.[0]) : .[1] }
所以你想要写一些类似的东西:
map(.Config.Env |= (map( split("=") | { (.[0]) : .[1] } ) | add))
抽象出数组到对象的功能使解决方案更容易消化:
def a2o: map( split("=") | { (.[0]) : .[1] } ) | add;
map(.Config.Env |= a2o)
match
或capture
代替split
因为" ="字符出现在"值"每个var=value
字符串的一部分,天真地使用split
可能不是一个好主意。假设您的jq支持正则表达式,这是一个更强大的替代方法:
match("([^=]*)=(.*)") | .captures | {(.[0].string) : .[1].string}
或者,更简洁,也许更优雅:
[capture( "(?<key>[^:]*):(?<value>.*)" )] | from_entries
index/1
如果您的jq没有正则表达式支持,您可以使用index/1
,这些行:
index("=") as $ix | {(.[:$ix]) : .[$ix+1:]}
答案 1 :(得分:0)
给定要转换为单个对象的项目集合,我通常会选择使用reduce
来实现此目的。将这些项目变成其组成键和值,然后分配给结果对象。
reduce (.[] | split("=")) as [$key, $value] ({}; .[$key] = $value)
虽然在这里也使用from_entries
也很有用,但您可以创建它期望的键/值对象的数组。
map(split("=") as [$key, $value] | {$key, $value}) | from_entries
然后使用您选择的任何一种方法将所有这些与Env
属性的更新放在一起。
.[].Config.Env |= reduce (.[] | split("=")) as [$key, $value] ({}; .[$key] = $value)
#or
.[].Config.Env |= (map(split("=") as [$key, $value] | {$key, $value}) | from_entries)