jq Cheat Sheet: Process AWS CLI and kubectl JSON Output
What is jq #
jq is a command line JSON processor. The AWS CLI and kubectl can print JSON, and jq turns that output into exactly the values or tables you need.
sudo apt install -y jq # macOS: brew install jq
jq --version
The basics #
echo '{"name":"web","port":80,"tags":["a","b"]}' > sample.json
jq . sample.json # pretty print
jq .name sample.json # "web"
jq -r .name sample.json # web (raw, no quotes)
jq '.tags[0]' sample.json # "a"
jq '.tags | length' sample.json # 2
jq 'keys' sample.json
AWS CLI examples #
aws ec2 describe-instances | jq '.Reservations[].Instances[] | {id: .InstanceId, type: .InstanceType, state: .State.Name}'
.Reservations[] iterates the array, the second [] iterates the instances, and {...} builds a smaller object.
# only running instances, one id per line
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
# tags as a map: {"Name":"web","Env":"dev"}
aws ec2 describe-instances | jq '.Reservations[].Instances[] | {id: .InstanceId, tags: ((.Tags // []) | map({(.Key): .Value}) | add)}'
# the Name tag
aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | [.InstanceId, (.Tags[]? | select(.Key=="Name") | .Value)] | @tsv'
# count instances by state
aws ec2 describe-instances | jq '[.Reservations[].Instances[].State.Name] | group_by(.) | map({state: .[0], count: length})'
# S3 buckets older than a date
aws s3api list-buckets | jq -r '.Buckets[] | select(.CreationDate < "2025-01-01") | .Name'
The AWS CLI also has its own filter, --query, written in JMESPath: aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId' --output text. Use --query for simple extractions and jq when you need to reshape, group or combine.
kubectl examples #
kubectl get pods -o json | jq -r '.items[].metadata.name'
kubectl get pods -A -o json | jq -r '.items[] | select(.status.phase!="Running") | "\(.metadata.namespace)/\(.metadata.name) \(.status.phase)"'
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, cpu: .status.capacity.cpu, memory: .status.capacity.memory}'
kubectl get deploy -o json | jq '.items[] | {name: .metadata.name, image: .spec.template.spec.containers[].image}'
"\(...)" is string interpolation. Restart counts per pod:
kubectl get pods -o json | jq -r '.items[] | [.metadata.name, ([.status.containerStatuses[]?.restartCount] | add)] | @tsv'
Operators to remember #
| Filter | Meaning |
|---|---|
.a.b, .a[], .a[0] |
Field, every element, first element |
select(cond) |
Keep what matches |
map(f) |
Apply f to every element |
{a, b: .c} |
Build an object |
.x // "default" |
Default when null |
.x? |
Ignore errors if missing |
group_by(.k), sort_by(.k), unique |
Group, sort, deduplicate |
to_entries, from_entries |
Object to key/value list and back |
@csv, @tsv, @json, @base64 |
Output formats |
Shell variables and files #
env=prod
jq --arg env "$env" '.[] | select(.Env==$env)' data.json # pass a string
jq --argjson n 3 '.[:$n]' data.json # pass a number
jq -s 'add' a.json b.json # merge files
jq -c '.items[]' data.json # one object per line
Edit a JSON file safely by writing to a new file: jq '.port = 8080' in.json > out.json && mv out.json in.json.
Related #
- AWS CLI cheat sheet and kubectl cheat sheet.
- Terraform output as JSON:
terraform output -json | jq -r .vpc_id.value.