Skip to content

jq cheat sheet

jq filters for pulling fields, filtering arrays, reshaping objects and emitting CSV or shell lines, each one run against the sample file on this page.

By Pushkar Kumar Verified against jq 1.8.2 Updated

Five jq filters cover most work: .field to read a value, .[] to walk an array, select(...) to keep only matching items, {a, b} to build a smaller object, and -r with @tsv or string interpolation to get plain text out for a shell. Every example below runs against the sample file shown first, and every one without a special flag is executed by this site’s test suite with the same jq build the jq Playground runs in your browser.

The sample, saved as services.json:

json
{
  "cluster": "prod-eu",
  "updated": "2026-10-01T12:00:00Z",
  "services": [
    {
      "name": "api",
      "env": "prod",
      "replicas": 3,
      "image": "registry.example.com/api:1.4.2",
      "ports": [8080],
      "labels": { "team": "core", "tier": "backend" }
    },
    {
      "name": "web",
      "env": "prod",
      "replicas": 2,
      "image": "registry.example.com/web:2.0.0",
      "ports": [80, 443],
      "labels": { "team": "frontend" }
    },
    {
      "name": "worker",
      "env": "staging",
      "replicas": 1,
      "image": "registry.example.com/worker:0.9.1",
      "ports": [],
      "labels": { "team": "core", "tier": "batch" }
    }
  ]
}

Read values

CommandWhat it does
jq '.' services.jsonPretty-print and validate. A syntax error in the file is reported with its line and column.
jq -c '.' services.jsonThe whole document on one line.
jq '.cluster' services.jsonOne field, as JSON: "prod-eu".
jq -r '.cluster' services.jsonThe same without quotes: prod-eu.
jq '.services[0].name' services.jsonIndex into an array; counting starts at 0.
jq '.services[-1].name' services.jsonNegative indexes count from the end: "worker".
jq '.services[1:]' services.jsonA slice: every service after the first.
jq '.services[].name' services.jsonOne output per array element.
jq '.services | length' services.jsonHow many items: 3.
jq 'keys' services.jsonThe top-level keys, sorted.
jq '.region // "unknown"' services.jsonA default when the key is missing or null.
jq '.. | .image? // empty' services.jsonFind a key at any depth.
jq 'getpath(["services", 0, "name"])' services.jsonRead a value from a path held as data.

Filter

CommandWhat it does
jq '.services[] | select(.env == "prod") | .name' services.jsonNames of production services.
jq '.services[] | select(.replicas > 1) | .name' services.jsonNumeric comparison.
jq '.services[] | select(.labels.tier == "batch") | .name' services.jsonMatch on a nested field.
jq '.services[] | select(.name | test("^w")) | .name' services.jsonRegular-expression match.
jq '.services[] | select(.ports | index(443)) | .name' services.jsonItems whose array contains a value.
jq '.services[] | select(.ports | length == 0) | .name' services.jsonItems with an empty array.
jq 'any(.services[]; .replicas == 0)' services.jsontrue if any item matches.
jq 'all(.services[]; .image | startswith("registry.example.com/"))' services.jsontrue only if every item matches.
jq 'first(.services[] | select(.env == "prod")) | .name' services.jsonStop at the first match.
jq 'limit(2; .services[]) | .name' services.jsonAt most two results.

Reshape

CommandWhat it does
jq '.services[] | {name, replicas}' services.jsonA smaller object per item; {name} is short for {name: .name}.
jq -c '.services[] | {name, tag: (.image | split(":")[1])}' services.jsonRename and compute fields.
jq '[.services[].name]' services.jsonCollect results back into an array.
jq '.services | map(.name)' services.jsonThe same with map.
jq '.services | map({(.name): .replicas}) | add' services.jsonTurn an array into an object keyed by name.
jq '.services | sort_by(.replicas) | map(.name)' services.jsonSort by a field.
jq '.services | max_by(.replicas) | .name' services.jsonThe item with the largest value.
jq '.services | group_by(.env) | map({env: .[0].env, count: length})' services.jsonGroup and count.
jq '.services | map(.labels.team) | unique' services.jsonDistinct values.
jq '[.services[].replicas] | add' services.jsonSum a field: 6.
jq 'reduce .services[] as $s (0; . + $s.replicas)' services.jsonThe same sum with an explicit accumulator.
jq '.services[0].labels | to_entries' services.jsonAn object as a list of {key, value} pairs.
jq 'with_entries(select(.key != "services"))' services.jsonDrop keys by a rule.
jq -c 'paths(type == "number")' services.jsonThe path to every number in the document.

Edit

CommandWhat it does
jq '.services[].replicas += 1' services.jsonUpdate every matching value in place; the rest of the document is kept.
jq '.services[0].env = "canary"' services.jsonSet one value.
jq '.services |= map(select(.env == "prod"))' services.jsonReplace an array with a filtered copy.
jq 'del(.updated)' services.jsonRemove a key.
jq 'del(.services[] | select(.env == "staging"))' services.jsonRemove matching array items.
jq '. + {owner: "platform"}' services.jsonMerge in new keys.

jq never edits the file itself. To save a change, write to a temporary file and move it over the original once jq succeeds.

Text output for scripts

CommandWhat it does
jq -r '.services[] | "\(.name)=\(.replicas)"' services.jsonString interpolation, one line per item.
jq -r '.services[] | [.name, .env, .replicas] | @tsv' services.jsonTab-separated rows, ready for column -t or cut.
jq -r '.services[] | [.name, .replicas] | @csv' services.jsonCSV with strings quoted.
jq -r '.services[] | @sh "docker pull \(.image)"' services.jsonShell commands with each value safely quoted.
jq -r '.cluster | @base64' services.jsonBase64-encode a value; @base64d decodes.
jq -r '.cluster as $c | .services[] | "\($c)/\(.name)"' services.jsonKeep an outer value in a variable while walking inside.
jq -r '.updated | fromdate | strftime("%Y-%m-%d")' services.jsonParse an ISO 8601 timestamp and reformat it.
jq -r '.services[] | try (.labels.tier | ascii_upcase) catch "no tier"' services.jsonHandle an error per item instead of stopping: web has no tier, so it prints no tier between BACKEND and BATCH.

Several inputs, or none

CommandWhat it does
jq -s 'length' services.jsonSlurp every JSON value in the input into one array first.
jq -s '.[0].cluster' services.jsonRead from the slurped array.
jq -n '{name: "api", replicas: 3}'Build JSON from scratch, reading no input.
jq -n '[inputs | .cluster]' services.jsonWith -n, read the input stream yourself with inputs.

Flags you will want

These change how jq is invoked rather than what the filter does.

CommandWhat it does
jq --arg env prod '.services[] | select(.env == $env) | .name' services.jsonPass a shell value in as the string $env.
jq --argjson min 2 '.services[] | select(.replicas >= $min) | .name' services.jsonPass a number or JSON value as $min.
jq -e '.services[] | select(.name == "api")' services.jsonExit 1 if the last result is false or null, and 4 if there was no result, so if jq -e … works in scripts.
jq -R 'split(",")'Read raw lines of text instead of JSON, one string per line.
jq -S '.' services.jsonSort object keys in the output, handy before a diff.
jq -j '.services[].name' services.jsonRaw output without a newline after each result.
jq --tab '.' services.jsonIndent with tabs instead of two spaces.

Gotchas

Gotcha: quote the filter in single quotes on Linux and macOS. Inside double quotes the shell expands $name and backticks before jq ever sees them.

Gotcha: redirecting jq’s output into its own input file (> services.json) empties it, because the shell truncates the file before jq reads it. Write to a temporary file, then move it over the original.

Gotcha: a missing key is null, not an error, so a typo in a field name prints null and exits 0. Use -e when a script must notice.

Gotcha: .[] on an object iterates its values, not its keys. Use keys or to_entries when you need the names.

Go deeper: paste your own JSON into the jq Playground to try any line above, or convert it to YAML with the JSON to YAML converter. For JSON that comes out of docker inspect, the Docker cheat sheet shows where it comes from.

Sources

Every command above was checked against these official references and against jq 1.8.2.

All cheat sheets

FAQ

Questions, answered.

Tap a question to expand the answer.

Add -r (raw output). jq '.name' prints "api" as a JSON string with quotes; jq -r '.name' prints api, which is what you want when the result goes into a shell variable.

Use --arg for strings and --argjson for numbers, booleans or JSON. For example jq --arg env "$ENV" '.services[] | select(.env == $env)'. Never splice the variable into the filter text with double quotes; it breaks on quotes and can change what the filter does.

Asking for a key that does not exist returns null rather than failing. Use the alternative operator (.region // "unknown") to supply a default, or -e so the exit status tells a script the last result was null or false.