使用 jq 将 x=y 对转换为键/值对 [英] Use jq to turn x=y pairs into key/value pairs
问题描述
我正在尝试从 docker inspect
的 JSON 输出中解析环境变量.令人讨厌的是,这些环境变量不会作为有用的键值对返回.它们只是 x=y 字符串的数组.这是输出的相关片段:
I'm trying to parse environment variables from the JSON output of docker inspect
. Annoyingly, those environment variables aren't returned as useful key-value pairs. They're just an array of x=y strings. Here's a relevant snippet of the output:
[
{
"Config": {
"Env": [
"JENKINS_HOST=1.2.3.4",
"JENKINS_INSTANCE=tea",
"JENKINS_NAME=Enterprise Architecture Tools",
"JENKINS_VERSION=2.46.2",
"JENKINS_PROTOCOL=http"
]
}
}
]
我想将该数组转换成这样的:
I would like to convert that array into something like this:
{
"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'
来获取我关心的值.我不知道如何做到这一点.
That way, I can use a command like jq '.[] | .Config.Env.JENKINS_HOST'
to get the values that I care about. I can't figure out how to accomplish this.
选择数据甚至将键和值拆分为单独的元素相对容易.例如,如果我使用 jq '.[] |.Config.Env |.[] |split("=")'
,我得到这样的数据:
It's relatively easy to select the data and even split the key and value into separate elements. For instance, if I use jq '.[] | .Config.Env | .[] | split("=")'
, I get data like this:
[
"JENKINS_HOST",
"1.2.3.4"
]
[
"JENKINS_INSTANCE",
"tea"
]
[
"JENKINS_NAME",
"Enterprise Architecture Tools"
]
[
"JENKINS_VERSION",
"2.46.2"
]
[
"JENKINS_PROTOCOL",
"http"
]
但是,我不知道如何将这些数据转换为对象分配.似乎它应该是 map
或 reduce
的某种组合,但我很难过.谁能指出我正确的方向?
However, I can't figure out how to turn that data into an object assignment. It seems like it should probably be some combination of map
or reduce
, but I'm stumped. Can anyone point me in the right direction?
推荐答案
要将包含两个字符串(例如 ["k", "v"])的数组转换为对象,可以这样写:
To convert an array of two strings (e.g. ["k", "v"]) to an object, you can write:
{ (.[0]) : .[1] }
所以你会想写这样的东西:
So you'll want to write something like:
map(.Config.Env |= (map( split("=") | { (.[0]) : .[1] } ) | add))
a2o
抽象出数组到对象的功能使解决方案更容易理解:
a2o
Abstracting out the array-to-object functionality makes the solution a bit more digestible:
def a2o: map( split("=") | { (.[0]) : .[1] } ) | add;
map(.Config.Env |= a2o)
使用 match
或 capture
代替 split
由于="字符可能出现在每个 var=value
字符串的值"部分中,因此天真地使用 split
可能不是这样的好点子.假设您的 jq 支持正则表达式,这是一个更强大的替代方案:
Using match
or capture
instead of split
Since it is possible for an "=" character to appear in the "value" part of each var=value
string, using split
naively might not be such a great idea. Here is a more robust alternative, assuming your jq supports regular expressions:
match("([^=]*)=(.*)") | .captures | {(.[0].string) : .[1].string}
或者,更简洁,也许更优雅:
Or, slightly more succinctly and perhaps elegantly:
[capture( "(?<key>[^:]*):(?<value>.*)" )] | from_entries
index/1
如果您的 jq 不支持正则表达式,您可以使用 index/1
,如下所示:
index("=") as $ix | {(.[:$ix]) : .[$ix+1:]}
这篇关于使用 jq 将 x=y 对转换为键/值对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!