Command-line options and passing variables

jq · Practical · 10 min

Scripts need clean output, correct exit codes and safe injection of shell variables, never string-pasting into the filter.

The flags you will use constantly:

  • -r raw strings, -c compact one-line output, -j like -r without newlines.
  • -n (null input) runs the filter once with null as input instead of reading stdin, used to generate JSON.
  • -s (slurp) reads all inputs into one array, e.g. to sort or count newline-delimited JSON records.
  • -e sets the exit status from the last output: 1 if it was false or null, 0 otherwise. Great for if jq -e '.ready' status.json; then ....
  • -S sorts object keys, --tab / --indent n control formatting.
  • -R reads raw lines of text as strings; -Rs reads the whole input as one string.

Passing values in. Never build the filter with shell interpolation like "select(.name == \"$name\")": quotes in the value break it, and it is an injection risk. Instead:

  • --arg name "$value" defines $name as a string.
  • --argjson n 5 parses the value as JSON (number, object...).
  • --slurpfile x file.json loads a file's values as an array in $x.
  • $ENV.HOME or env.HOME reads environment variables.
  • --args after the filter makes remaining arguments available in $ARGS.positional.

Combine -n with --arg to build request bodies safely for curl.

Example

echo '[{"name":"Ann","age":31},{"name":"Bob","age":25}]' > p.json
n="Ann"
jq --arg n "$n" '.[] | select(.name == $n) | .age' p.json   # 31
jq --argjson min 30 -c 'map(select(.age >= $min))' p.json    # [{"name":"Ann","age":31}]
jq -n --arg user "$USER" --argjson admin true '{user: $user, admin: $admin}' -c
# {"user":"alice","admin":true}
printf '{"v":1}
{"v":2}
' | jq -s 'map(.v) | add'          # 3
printf 'a
b
' | jq -R -c '[., length]'                    # ["a",1] ["b",1]
echo '{"ready":false}' | jq -e .ready >/dev/null; echo $?  # 1
jq -n '$ENV.HOME'                                          # "/home/alice"

Remember

  • -r raw, -c compact, -n no input, -s slurp, -e exit status
  • --arg (string) and --argjson (JSON) pass values safely
  • -n with --arg builds JSON for other tools

Watch out for

  • Splicing shell variables into the filter text instead of using --arg.

Check yourself

  1. `count=5` in the shell. Which passes it as a number to jq?
  2. What does `-s` do with three newline-separated JSON objects on stdin?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: jqlang.org/manual/