Converting a JSON array to a bash array
Bash is the most common language of DevOps because you can guarantee that it’s installed on a server.
Bash is not pretty. It’s not an elegant language. It’s better than, like, C, but it’s still awkward and clunky.
Anyway, I love bash, so that’s enough of that.
One of the (great many) things that bash is persnickety about is list format:
- A JSON array looks like this:
[ 1, 'Thing 2', 3 ]
- A bash array looks like this:
( 1 'Thing 2' 3 )
The problem
The problem is twofold:
- A great many APIs return output in JSON format, but bash has no way to loop through it.
- Languages that can parse JSON format easily don’t always have library support for whatever it is you’re interacting with. (In my case, I had to revert to bash because GCP is still catching up to AWS in the “API support” race.)
The solution: bash/sed string manipulation
Below, I run a gcloud command and use JQ to grab an array from its JSON output, then do a little sed/regex magic and convert it to proper bash format:
# using gcloud output as a source because why not use the hardest shit possible
bork=$(gcloud --project=<project-id> container images list-tags us.gcr.io/<project-id>/<image-name> --filter='tags:DEPLOYED' --format=json | jq '.[0].tags')
echo $bork
[ "260", "61a1d7aef75421f5c209c42304716ba44e86ab7a", "DEPLOYED.2019-11-12T17.04.37.772145800Z", "DEPLOYED.2019-11-13T00.00.29.525908800Z" ]
# ^ output is obviously not a bash array
# strip out all the things you don't want - square brackets and commas
borkstring=$(echo $bork | sed -e 's/\[ //g' -e 's/\ ]//g' -e 's/\,//g')
arr=( $borkstring )
echo $arr
( "260" "61a1d7aef75421f5c209c42304716ba44e86ab7a" "DEPLOYED.2019-11-12T17.04.37.772145800Z" "DEPLOYED.2019-11-13T00.00.29.525908800Z" )
# ^ now THAT is a bash array
Parsing your new bash array
Cool. You’ve got your bash array. Now what? Loop through it.
Here I’m just using echo inside this loop, but ultimately I used this loop to add tags to a copy of this container image that I stuck in another project. The story behind that decision is long and boring.
# loop through that lil bebe
for i in ${arr[@]}; do
# add a little native bash quote-stripping in there; without it,
# all your array elements will be wrapped in quotes.
echo ${i//\"}
done
The Output
260
61a1d7aef75421f5c209c42304716ba44e86ab7a
DEPLOYED.2019-11-12T17.04.37.772145800Z
DEPLOYED.2019-11-13T00.00.29.525908800Z