shell loop structured data

json all the things

SEAN K.H. LIAO

shell loop structured data

json all the things

shell loop with structured data

So, again I've found a need to loop over a set of instances with multiple pieces of metadata for each instance in a shell script. In a proper programming language, I'd just define a list of objects, and loop over that. Example (in Go):

 1func f(){
 2  tasks := []struct{
 3    name string
 4    url string
 5    account_id int
 6  }{
 7    {
 8      "instance1", "https://a.example", 1,
 9    }, {
10      "instance2", "https://b.example", 2,
11    }
12  }
13  for _, task := range tasks {
14    // do the things here
15    _ = task.url
16  }
17}

jq to the rescue

Bash and most other shells don't have high dimensional data structures. You get lists, hashmaps and that's it. You could sort of fake it with weird key structures, but I'd rather not.

So why not just use json and jq.... Of course, replace json+jq with yaml+yq or xml+yq or...

 1cat << EOF > data.json
 2[{
 3  "name": "instance1",
 4  "url": "https://a.example",
 5  "account_id": 1
 6},{
 7  "name": "instance2",
 8  "url": "https://b.example",
 9  "account_id": 2
10}]
11EOF
12
13for name in $(jq '.[] | .name' data.json); do
14  # do the things here
15  url=$(jq --arg name "${name}" '.[] | select(.name == "\($name)") | .url' data.json)
16done