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?
Given collection of items to convert to a single object, I generally would opt to using
reduce
for this purpose. Turn those items to their constituent keys and values, then assign to the result object.Though using
from_entries
is also useful here as well, instead you'd create an array of the key/value objects that it expects.Then put it all together with the update of the
Env
property using whichever method you choose.https://jqplay.org/s/qfItW5U-Tf
To convert an array of two strings (e.g. ["k", "v"]) to an object, you can write:
So you'll want to write something like:
a2o
Abstracting out the array-to-object functionality makes the solution a bit more digestible:
Using
match
orcapture
instead ofsplit
Since it is possible for an "=" character to appear in the "value" part of each
var=value
string, usingsplit
naively might not be such a great idea. Here is a more robust alternative, assuming your jq supports regular expressions:Or, slightly more succinctly and perhaps elegantly:
index/1
If your jq does not have regex support, you could use
index/1
, along these lines: