LinuxII · Shell and Command-Line OperationsStructured text
jq and structured text — JSON, YAML, and CSV at the command line
What you'll learn
- Use jq to extract, filter, and reshape JSON
- Recognise when YAML and CSV warrant a different tool
- Build jq pipelines that handle missing keys and arrays
- Avoid the common jq mistakes that produce empty results
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09
Modern infrastructure tooling speaks JSON: cloud APIs, container
runtimes, monitoring agents, configuration management, and most
service-discovery systems. jq is the universal JSON processor on
Linux and is the right tool for almost every JSON triage task.
The basic jq filter
A jq filter describes what to extract from a JSON value:
echo '{"name":"web01","status":"running"}' | jq '.name'
# "web01"
The leading . is the identity filter; .name selects the name
field. By default jq pretty-prints its output.
$ echo "{\"name\":\"web01\",\"status\":\"running\"}" | jq ".name""web01"Illustrative output
$ echo '{"name":"web01","status":"running"}' | jq -r '.name'web01Illustrative output
Arrays and iteration
A JSON array is iterated with [] or , (the comma form generates
multiple output records):
$ echo '[{"name":"web01"},{"name":"db01"},{"name":"cache01"}]' | jq -r '.[].name'web01
db01
cache01Illustrative output
$ echo '[{"name":"web01","status":"running"},{"name":"db01","status":"stopped"}]' | jq -r '.[] | select(.status == "running") | .name'web01Illustrative output
Nested objects
For nested objects, use . chaining or […] for bracketed paths:
$ echo '{"host":{"network":{"ip":"10.0.0.5"}}}' | jq -r '.host.network.ip'10.0.0.5Illustrative output
$ echo '{"items":[{"name":"a"},{"name":"b"}]}' | jq -r '.items[] | .name'a
bIllustrative output
Constructing output
jq can build new JSON objects from the input:
$ echo '[{"name":"web01","port":8080},{"name":"db01","port":5432}]' | jq -r '.[] | "(.name):(.port)"'web01:8080
db01:5432Illustrative output
$ echo '[{"name":"web01","port":8080}]' | jq '[.[] | {host: .name, port: .port}]'[
{
"host": "web01",
"port": 8080
}
]Illustrative output
Handling missing keys gracefully
A common jq mistake is getting the literal text null for keys that do not exist in every record. The fix is the alternative operator. In jq that means two slash characters in a row
This file had MDX parser issues that the build process is recovering from.
$ echo '[{"name":"web01"},{"name":"db01","port":5432}]' | jq -r '.[] | "(.name):(.port // "unknown")"'web01:unknown
db01:5432Illustrative output
YAML and CSV
YAML and CSV are common in infrastructure but lack jq’s universal filters:
$ yq -r '.spec.containers[].image' deployment.yamlnginx:1.27
prom/node-exporter:1.8Illustrative output
$ python3 -c 'import csv,sys; r=csv.DictReader(sys.stdin); print("\n".join(row["name"] for row in r))' < users.csvalice
bob
carolIllustrative output
Knowledge check
Knowledge check · 3 questions
Q1. What is the effect of jq's -r flag?
Q2. jq is installed by default on every modern Linux distribution.
Q3. Which of the following are correct jq idioms? Select all that apply.
Passing score: 75%. Answers are checked in this browser.