Recall that a jq
program is a pipeline of expressions.
Variable assigmnent follows this rule: a variable assignment is an expression that looks like:
... | expr as $varname | ...
Like the identity expression .
, the variable assignment's output is the same as its input.
Setting the variable's value is a side-effect.
Example, showing .
after the assignment is the same as the initial input:
$ jq -c -n '42 | (. * 2) as $double | [., $double]'
[42,84]
The scope of the variable is "lexical" -- the variable will be in scope for the rest of the pipeline. Variables defined in functions (we'll get to functions later) are "local" to the function.
The variable must begin with $
.
The rest of the variable name is an identifier: starts with a letter or underscore followed by letters, numbers or underscores.
From the manual:
Multiple variables may be declared using a single
as
expression by providing a pattern that matches the structure of the input (this is known as "destructuring").
Examples:
[1, 2, 3] as [$a, $b, $c]
| [$a, $b, $c] # => [1, 2, 3]
{"foo": "bar", "len": [10, 20]} as {foo: $f, len: [$h, $w]}
| [$f, $h, $w] # => ["bar", 10, 20]
Matching the variable name to the object key offers a shortcut:
{"x": 4, "y": 7} as {$x, $y}
| [$x, $y] # => [4, 7]
{"foo": "bar", "len": [10, 20]} as {$foo, $len}
| [$foo, $len] # => ["bar", [10, 20]]
The same shortcut works in the reverse sense for object construction
4 as $x | 7 as $y | {$x, $y} # => {"x":4, "y": 7}
As shown in the above example, variables are handy for storing constants. It's better to give constants a name rather than have "magic numbers" show up in the code.
It is often more readable to omit variables.
Consider calculating the average of a list of numbers
[2, 4, 8, 7]
| add as $sum
| length as $len
| $sum / $len
compared to
[2, 4, 8, 7] | add / length
This highlights one of the most powerful aspects of jq
: the input to a filter is provided to every sub-expression:
[2,4,8,7]
is passed to add
(which sums the numbers by applying the +
operator to all the elements)[2,4,8,7]
is also passed to length