jq
Very often you will get content in JSON format. If you want to process this in bash scripting you will soon find out, it is very hard to do. JSON can have lots of optional line breaks and whitespaces, and in order to find a specific element you often need to almost parse the structure. But worry no more:
jq manual
https://stedolan.github.io/jq/manual/v1.6/
Identity
Just copies all that is there, but pretty print
| jq "."
{
"name": "John",
"age": 42,
"colors": [
"red",
"green",
"blue"
]
},
{
"name": "John",
"age": 42,
"colors": [
"red",
"green",
"blue"
]
}
]
Get a single field
| jq ".address.zipcode"
Arrays
You have an array / list of objects
Get all the elements of the array
| jq ".[]"
"name": "John",
"age": 42,
"colors": [
"red",
"green",
"blue"
]
}
{
"name": "Jane",
"age": 35,
"colors": [
"yellow",
"red",
"blue"
]
}
Get only the first element
| jq ".[1]"
Get the last element
| jq ".[-1]"
Get the first 3 element
jq ".[0:2]"
Multiple fields
| jq ".name, .age"
42
Somewhere in the object is an array
First copy some fields + the array (boring)
| jq "{name, age, colors: .colors }"
Now have for each entry in the array an extra output line
| jq "{name, age, colors: .colors[] }"
(:source lang=Bash:) [@
{
"name": "John",
"age": 42,
"colors": "red"
}
{
"name": "John",
"age": 42,
"colors": "green"
}
{
"name": "John",
"age": 42,
"colors": "blue"
}
If you want to iterate about an json array use this to get each entry of the Array in one line
do
echo "$line" | jq
done
Pipe
Have several commands and the output of the first, goes to the second, ... Like a Unix "|"
Array 1 by 1, from the result only take 2 fields
| jq ".[] | .name, .age"
Build new objects
Take the fields with values and build a new object. This builds the same object again
| jq "{name, age}"
This
is a short form of
The long form is required if you need to access fields inside the data, e.g. person.age. As the short form would try to name the field otherwise with a dot in it and fail.
You can also take field name and field value separately
| jq "{name: .name, age: .age}"
And of course change them
| jq ".[] | { "TheName": .name, age: 43 }"
Filtering (like with grep)
| jq ".[] | select(.name == \"Jane\")"
"name": "Jane",
"age": 35,
"colors": [
"yellow",
"red",
"blue"
]
}