How to Pass Shell Variables to jq with --arg and --argjson
Use --arg name "$value" to pass a string from your shell into jq. Use --argjson name "$value" when the value is valid JSON and must keep its type (number, boolean, array, object, or null). Inside the jq filter, refer to either as $name. Keep the filter in single quotes so your shell does not try to expand jq's $name itself.
Save this input as input.json for both examples:
{
"owner": "Ada",
"min_total": 0,
"orders": [
{
"id": "a",
"total": 12
},
{
"id": "b",
"total": 25
}
]
}
Pass a string safely with --arg
owner="O'Reilly & Sons"
jq --arg owner "$owner" \
'.owner = $owner' input.json
Output:
{
"owner": "O'Reilly & Sons",
"min_total": 0,
"orders": [
{
"id": "a",
"total": 12
},
{
"id": "b",
"total": 25
}
]
}
The double quotes around "$owner" keep spaces and & in one shell argument; the apostrophe in the value is data, not jq syntax. The single-quoted jq expression leaves $owner for jq to resolve. Do not construct a filter by inserting untrusted shell text into the jq program.
Pass a number with --argjson
Using the same input.json, keep the threshold numeric to select orders totaling at least 20:
minimum=20
jq --argjson minimum "$minimum" '
.orders | map(
select(.total >= $minimum)
)
' input.json
Output:
[
{
"id": "b",
"total": 25
}
]
--argjson parses 20 as the JSON number 20. It also accepts valid JSON such as true, null, or '{"limit":20}'; quote structured JSON as one shell argument. Invalid JSON, such as twenty, is rejected rather than silently converted to a string.
Watch for a numeric/string mismatch
Changing only the option to --arg makes $minimum the string "20":
jq --arg minimum "$minimum" '
.orders | map(
select(.total >= $minimum)
)
' input.json
Output:
[]
jq orders numbers below strings when comparing different types, so neither numeric total passes >= "20"; the empty result is not proof that no order meets the numeric threshold. Arithmetic makes the mismatch explicit:
jq --arg minimum "$minimum" '
.orders | map(.total + $minimum)
' input.json
This command fails with a jq type error: number (12) and string ("20") cannot be added. Use --argjson for a numeric threshold, and validate external values before passing them as JSON.
These are jq CLI commands, verified with jq 1.8.1 in a POSIX-style shell; they are not runnable playground prefills. The browser jq playground accepts a JSON input and a jq filter, but not shell variables or CLI flags. For more transformations, see update fields with jq, check whether a key exists, and the jq cheatsheet. Reference: jq manual, invoking jq and types and values.