使用jq将x = y对转换成键/值对 [英] Use jq to turn x=y pairs into key/value pairs
问题描述
我正在尝试从 docker inspect
的JSON输出中解析环境变量。令人遗憾的是,这些环境变量不会作为有用的键值对返回。它们只是一个x = y字符串的数组。以下是输出的相关代码段:
[
/ pre>
{
配置:{
Env:[
JENKINS_HOST = 1.2.3.4,
JENKINS_INSTANCE =茶,
JENKINS_NAME =企业架构工具,
JENKINS_VERSION = 2.46.2,
JENKINS_PROTOCOL = http
]
}
}
]
我想将该数组转换成如下所示:
JENKINS_NAME:企业架构工具,
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,
企业架构工具
]
[
JENKINS_VERSION,
2.46.2
]
[
JENKINS_PROTOCOL,
http
]
但是,我无法弄清楚如何将数据转换为对象分配。似乎它应该是 map
或 reduce
的组合,但我被困住了。任何人都可以指向正确的方向?
要转换两个字符串的数组(例如[k,v ])到一个对象,你可以写:
{(。[0]):。[1]}
所以你想写一些如下的东西:
map(.Config.Env | =(map(split(=)| {(。[0]):。[1]})| add))
a2o
抽出数组到对象功能使解决方案更易消化:
def a2o:map(split(=)| {(。[0 ]):。[1]})|加;
地图(.Config.Env | = a2o)
使用 match
或 capture
而不是 split
由于可以在每个 var = value
字符串的值部分中显示=字符,因此使用 split
天真地可能不是一个好主意。这是一个更强大的替代方案,假设你的jq支持正则表达式:
match(([^ =] *)= 。*))| .captures | {(。[0] .string):。[1] .string}
或者稍微多一些简洁而又优雅地:
[capture((?< key> [^:] *)值>。*))] | from_entries
index / 1
如果您的jq没有正则表达式支持,可以使用 index / 1
,这些行:
index(=)as $ ix | {(。[:$ ix]):。[$ ix + 1:]}
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"
}
}
}
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.
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"
]
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?
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
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)
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
If your jq does not have regex support, you could use index/1
, along these lines:
index("=") as $ix | {(.[:$ix]) : .[$ix+1:]}
这篇关于使用jq将x = y对转换成键/值对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!