jq and bash, part II
Yesterday we saw how to read key/value pairs from a JSON document and map them into a bash friendly format. Today we finish the job with a read/while loop.
A read/while loop is a simple bash construct that loops over input and maintains the integrity of each line. This is perfect for dealing with JSON key/value pairs.
As a reminder, here’s the output of our jq command:
jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json"
#=> data=Click Here
#=> size=36
#=> style=bold
The key is to pipe the jq output into a while loop, which is done by enclosing the jq command in a < <( )
syntax. Check out the basic implementation:
while read line; do
echo $line
done < <(jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json")
#=> data=Click Here
#=> size=36
#=> style=bold
Great. We’re almost there. Now we just need to extract the key / value pairs. This is done by specifying the internal field separator or IFS, which is an internal bash variable that denotes the char which separates words. It defaults to a white space, but we can use any char we want. In this case we will use the =
sign.
while IFS="=" read key value; do
echo "key is '$key'"
echo -e "value is '$value'\n"
done < <(jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json")
#=> key is 'data'
#=> value is 'Click Here'
#=> key is 'size'
#=> value is '36'
#=> key is 'style'
#=> value is 'bold'
This is awesome. We now have access to the JSON data as easily as if we were in a JavaScipt application. Now we can do whatever we need to do with the data. My recent use case was setting environmental variables:
while IFS="=" read key value; do
export $key="$value"
echo "env var '$key' is set to ${!key}"
done < <(jq -r ".widget.text|to_entries|map(\"\(.key)=\(.value)\")|.[]" < "example.json")
#=> env var 'data' is set to Click Here
#=> env var 'size' is set to 36
#=> env var 'style' is set to bold
Good stuff. With jq and a read while loop it becomes possible to make very robust bash scripts to accomplish many useful tasks.
Note: For a post about how I’m accessing the value of the env variable in that last example(${!key}
), see this post