Suppose we have the following JSON – {a:1,b:"x"}
. I want to extract the properties a
and b
and assign them to the respective bash variables.
Here is how I do it today:
/c/Temp$ export $(jq -n '{a:1,b:"x"}' | sed -n 's,:,=,p' | tr -d ', "') && echo $a && echo $b
1
x
/c/Temp$
However, this only works when the values do not contain spaces, therefore my solution is incorrect.
I can also invoke jq
one by one like this:
/c/Temp$ b=$(jq -n '{a:1,b:"x"}' | jq -r .b) && echo $b
x
/c/Temp$ a=$(jq -n '{a:1,b:"x"}' | jq -r .a) && echo $a
1
/c/Temp$
But I feel it is not the most concise solution.
What is the most concise solution?
For the purpose of this post, use this json:
{
"a": 1,
"b": "x y"
}
But the solution should work equally well for a JSON with 50 top level properties.
3
Answers
If the content of your JSON is trustworthy:
Output:
See: Why should eval be avoided in Bash, and what should I use instead?
If the input is valid JSON (as with your second input – the first one lacked quoting the
a
key), and the keys are valid identifiers for shell variables (with no special characters like=
or whitespace etc.), and the values don’t contain newlines (special characters like=
or other whitespace are covered, though), then you could useread
on a single jq filter as follows:For the two item version just name them directly:
For more items you could
declare
them in awhile
loop based on the output of ato_entries
iteration (in the shell, use variable names (here$key
and$value
) that are not affected by the extraction):For conciseness, you can have jq also generate the
=
between key and value, so only one variable (here$dec
) is needed: