From Json structure, I want a specific dictionary. From key's color yellow or red, I add id value.
[
{
"id": "9b058640",
"type": "db",
"color": "red",
"host": "db1"
},
{
"id": "0u858640",
"type": "db",
"color": "yellow",
"host": "db2"
},
{
"id": "0ui9k40",
"type": "net",
"color": "red",
"host": "net1"
},
{
"id": "5ty87a",
"type": "net",
"color": "yellow",
"host": "net2"
}
]
So I want to get the X dictionary
X=(
['yellow']="9b058640 5ty87a"
['red']="9b058640 0ui9k40"
)
I could parse by value :
jq -c '.[] | select(.color | contains("red"))'
CodePudding user response:
You can use the @tsv
operator in jq to emit tab-separated output, which a bash while read
loop can easily parse as input.
Assuming your input JSON is in the variable s
:
declare -A X=( )
while IFS=$'\t' read -r color id; do
X[$color] ="$id "
done < <(jq -r '.[] | [.color, .id] | @tsv' <<<"$s")
The above does take a minor shortcut in that it leaves a trailing space after each item. If that's unacceptable for some reason, you can always go through the array and clean it up after the fact with a second loop:
for color in "${!X[@]}"; do
X[$color]=${X[$color]%" "}
done
You can see this running in the sandbox at https://replit.com/@CharlesDuffy2/IndigoRemoteEngineering
Alternately, using eval
:
#!/usr/bin/env bash
case $BASH_VERSION in ''|[0-3].*) echo "ERROR: bash 4.0 required" >&2; exit 1;; esac
declare -A X=( )
eval "$(
jq -r '
reduce .[] as $item ({}; .[$item.color] = [$item.id])
| to_entries[]
| "X[\(.key | @sh)]=\(.value | join(" ") | @sh)"
'
)" <file.json
CodePudding user response:
No need for .
, source
, eval
or even looping in bash. All you need is declare
and jq
, which can construct the declaration using escaping with @sh
and string interpolation:
declare -A X="($(
jq -r '
[ ("yellow", "red") as $color
| @sh "[\($color)]=\(map(select(.color == $color).id) | join(" "))"
] | join(" ")
' input.json
))"
$ echo "${X[yellow]}"
0u858640 5ty87a
$ echo "${X[red]}"
9b058640 0ui9k40
CodePudding user response:
Answer:
declare -A a
. <(jq -r '"a[\(.color)] =${a[\(.color)] }\(.id)"' file.json)
Provides:
$ declare -p a
$ declare -A a=([red]="9b058640 0ui9k40" [yellow]="0u858640 5ty87a" )
# or
$ echo "${a[red]}"; echo "${a[yellow]}"
9b058640 0ui9k40
0u858640 5ty87a
Explanation:
- Construct the following bash code in
jq
: a[color] =${a[color] }id
${a[color] }
expands toa[color]
is empty."\(.id)"
is jq string interpolation - its replaced with the value of.id
- use
.
and a process sub to source this code