Every 'why did I get four results?' or 'why did nothing print?' puzzle in jq comes from its generator semantics.
Every jq expression is a generator: for one input it can emit zero, one or many outputs. .[] emits many, select emits zero or one, empty emits none, and , concatenates generators.
When an operator combines two generators, jq evaluates all combinations. That gives cartesian products:
(1,2) + (10,20)outputs four values:11, 12, 21, 22(the right operand varies in the outer loop).{a: (1,2), b: (3,4)}produces four objects.[.[] | .x] | lengthis safe, but.[].x + .[].ycombines every x with every y, a common accidental blow-up.
empty is meaningful: in if cond then . else empty end it removes the value, and select(f) is defined as if f then . else empty end. A function that produces empty inside [...] simply contributes nothing.
Under the hood jq backtracks: after emitting an output downstream, it resumes the generator for the next one. limit(n; f) and first(f) stop a generator early using label $out | ... break $out, which you can use yourself to exit a loop.
range(n), range(from; upto; by), recurse(f), repeat and until(cond; next) are generator building blocks. For loops with state prefer reduce/foreach, which run in constant stack, over deep recursive defs.
Example
jq -nc '[(1,2) + (10,20)]' # [11,12,21,22]
jq -nc '{a: (1,2), b: (3,4)} | [.a,.b]' # [1,3] [1,4] [2,3] [2,4]
jq -nc '[1,2,3] | [.[] | if . % 2 == 1 then . else empty end]' # [1,3]
jq -nc '[range(0; 10; 3)]' # [0,3,6,9]
jq -nc '[limit(3; repeat(1))]' # [1,1,1]
jq -nc '[label $out | range(10) | if . == 4 then break $out else . end]' # [0,1,2,3]
jq -nc '[1 | recurse(if . < 50 then . * 3 else empty end)]' # [1,3,9,27,81]
jq -nc '[2 | until(. > 100; . * 2)]' # [128]Remember
- Expressions emit zero, one or many outputs
- Binary operators combine all output pairs (cartesian product)
- empty emits nothing; label/break and limit stop generators early
Watch out for
- Combining two .[] expressions in one arithmetic or object expression and getting N x M results.