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:
-rraw strings,-ccompact one-line output,-jlike -r without newlines.-n(null input) runs the filter once withnullas 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.-esets the exit status from the last output: 1 if it wasfalseornull, 0 otherwise. Great forif jq -e '.ready' status.json; then ....-Ssorts object keys,--tab/--indent ncontrol formatting.-Rreads raw lines of text as strings;-Rsreads 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$nameas a string.--argjson n 5parses the value as JSON (number, object...).--slurpfile x file.jsonloads a file's values as an array in$x.$ENV.HOMEorenv.HOMEreads environment variables.--argsafter 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.