Say I have a yaml file, example.yaml
:
networks:
net:
driver: overlay
dockerfiles:
nodeapp: |
FROM node:18-alpine
WORKDIR /$NAME
services:
registry:
image: registry:2
ports:
- "5000:5000"
- "337:337"
pinger:
build:
context: .
dockerfile: nodeapp
deploy:
replicas: 3
I can convert to JSON using yq
, and then set the top level entries as variables with jq
:
eval $(yq e example.yaml -j | jq -r '..? | to_entries | .[] | .key + "=" + (.value|tostring)')
echo $services
{registry:{image:registry:2,ports:[5000:5000]},pinger:{build:{context:.,dockerfile:nodeapp},deploy:{replicas:3}}}
However, I cannot seem to get jq
to recursively go into the objects and set variables, so that echo $services_pinger_dockerfile
gives "nodeapp"
for example.
I've seen in the docs that there is a recursion operator. Can anyone suggest a way of doing this?
There are similar questions. But none that I found dealing with multilevel YAML/JSON to shell variables in this way.
jq: Getting two levels of keys
Extract JSON value to shell variable using jq
https://unix.stackexchange.com/questions/413878/json-array-to-bash-variables-using-jq
https://unix.stackexchange.com/questions/121718/how-to-parse-json-with-shell-scripting-in-linux
Why not process it directly with yq
?
eval $(yq e '.. | select(. == "*") | {(path | join("_")): . style="double"} ' example.yaml | sed -E 's/(.*): (.*)/\1=\2/g')
echo $services_pinger_build_dockerfile
yq
command was taken from this answer, see there for details.
The appended sed
rewrites a_b: "c"
into a_b="c"
, so we can then eval
it in bash. I do not use the technique you show because it would cause the values to not be quoted in the output, which is bad especially for multi-line strings.
The code outputs nodeapp
.