JSON Tools: Jq
grammar and invocation | variables and expressions | arithmetic and logic | strings | regular expressions | dates and time | arrays | dictionaries | functions | execution control | exceptions | streams | file formats | processes and environment | libraries and namespaces | reflection
version | |
---|---|
jq | |
version used |
1.5 |
show version |
$ jq --version |
grammar and execution | |
jq | |
interpreter | $ cat > hello.jq "Hello, World!" # -n: use single "null" as input # -r: write string content instead of quoted string literal to stdout $ jq -nr -f hello.jq Hello, World! |
command line program | $ echo '1 2 3' | jq '. * .' # no stdin: $ jq -n '1 + 1' |
statement separator | A program consists of filter expressions separated by commas and pipes: , | A filter expressions acts on its input and produces output. The pipe separator makes the output of the left expression the input of the right expression. The comma separator, which concatenates the output of two filters, has higher precedence than the pipe separator. A function definition, include statement, or import statement is terminated by a semicolon: ; |
block delimiters |
# Use parens to change precedence: $ jq -n '2, (3 | . * .)' $ jq -n '2, 3 | . * .' |
end of line comment |
# comment |
variables and expressions | |
jq | |
assignment | $ echo '[1,2,3]' | jq 'length as $x | map(. * $x)' "length as $x" assigns the value 3 to $x. The following filter receives the same input the assignment filter got. |
compound assignment | |= += -= *= /= %= //= Compound operators are used with arrays and dictionaries. A copy of the array or dictionary is returned, with fields specified on the LHS replaced by new values. If the compound assignment expression is "LHS OP= RHS", then the new value is "LHS OP RHS". # {"t": 2, "f": 0}: $ echo '{"t": 1, "f": 0}' | jq '.t += 1' More than one field can be updated. # {"t": 2, "f": 1}: $ echo '{"t": 1, "f": 0}' | jq '.[] += 1' |
null |
null |
null test |
$ echo '{"name": "Ed"}' | jq '.age == null' |
coalesce | # also replaces false: $ echo '{}' | jq '.age // 0' |
conditional expression |
$ echo '-3' | jq 'if . < 0 then -. else . end' |
arithmetic and logic | |
jq | |
true and false |
true false |
falsehoods |
null false |
logical operators |
and or not |
relational operators |
== != < > <= >= |
min and max |
$ echo '[1,2,3]' | jq 'min' $ echo '[1,2,3]' | jq 'max' |
arithmetic operators |
+ - * / % |
integer division | # floor is new in 1.4: $ jq -n '-13 / 5 | floor' |
division by zero |
error |
sqrt | # new in 1.4: $ jq -n '2 | sqrt' |
sqrt -1 | # null: $ jq -n '-1 | sqrt' |
transcendental functions | # new in 1.5: exp log sin cos tan asin acos atan |
float truncation | # floor is new in 1.4: $ jq '1.1 | floor' |
strings | |
jq | |
literal |
"lorem ipsum" |
newline in literal |
not allowed; use \n escape sequence |
string escapes |
\\ \" \/ \b \f \n \r \r \t \uhhhh |
variable interpolation |
$ echo '{"foo": 1, "bar": 2}' | jq '"\(.foo):\(.bar)"' |
concatenate |
"foo" + "bar" |
translate case | $ echo '"foo"' | jq 'ascii_upcase $ echo '"FOO"' | jq 'ascii_downcase' |
number to string |
$ echo '7' | jq 'tostring' |
string to number |
$ echo '"7"' | jq 'tonumber' |
string join | # join is new in 1.4: $ echo '["do", "re", "mi"]' | jq 'join(" ")' |
split | # split is new in 1.4: $ echo '"do re mi"' | jq 'split(" ")' # remove two empty strings: $ echo '" do re mi"' | jq 'split(" ") | map(select(length > 0))' |
prefix and suffix test | $ echo '"foobar"' | jq 'startswith("foo")' $ echo '"foobar"' | jq 'endswith("bar")' |
string length |
$ jq -R 'length' /etc/hosts |
index of substring first, last |
# 3: $ echo '"do re re"' | jq 'index("re")' # 6: $ echo '"do re re"' | jq 'rindex("re")' # null: $ echo '"do re re"' | jq 'rindex("mi")' |
regular expressions | |
jq | |
literal | # regexes are new in 1.5: "lorem|ipsum" |
character class abbrevations | but backslashes must be doubled inside double quotes: . \d \D \h \H \s \S \w \W |
anchors | but backslashes must be doubled inside double quotes: ^ $ \A \b \B \z \Z |
match test |
$ echo $'"It\'s 1999!"' | jq '. | test("1999")' |
case insensitive match test | $ echo $'"FOO BAR"' | jq 'test("foo"; "i")' $ echo $'"FOO BAR"' | jq 'test(["foo", "i"])' $ echo $'"FOO BAR"' | jq 'test("(?i)foo")' |
substitution first occurrence, all occurrences |
$ echo '"do re mi mi mi"' | jq 'sub("mi"; "ma")' $ echo '"do re mi mi mi"' | jq 'gsub("mi"; "ma")' |
named group capture |
$ echo '"foo.txt"' | jq 'capture("^(?<root>.*)\\.(?<suffix>.*)$") | .root' |
dates and time | |
jq | |
current datetime | # date/time functions are new in 1.5 # array of broken-down datetime values: $ jq -n 'now | gmtime' # ISO 8601 format: $ jq -n 'now | gmtime | todate' |
current unix epoch |
$ jq -n 'now' |
broken-down datetime to unix epoch | $ echo '[2016,11,15,11,30,0,4,349]' | jq 'mktime' |
unix epoch to broken-down datetime | $ echo 1481801400 | jq 'gmtime' |
format datetime |
$ jq -n 'now | gmtime | strftime("%Y-%m-%d %H:%M:%S")' |
parse datetime | # parses to array of broken-down datetime values: $ echo '"2016-12-15 11:30:00"' | jq 'strptime("%Y-%m-%d %H:%M:%S")' |
arrays | |
jq | |
lookup | # 6: $ echo '[6, 7, 8, 9'] | jq '.[0]' |
not-an-array behavior | # error: $ echo 1 | jq '.[0]' # no error and no output: $ echo 1 | jq '.[0]?' |
length | $ echo '[6, 7, 8, 9'] | jq 'length' |
slice | # [7, 8]: $ echo '[6,7,8,9]' | jq '.[1:3]' |
slice from beginning | $ jq -c '.[:2]' |
slice to end | from element 3 on: $ jq -c '.[2:]' last two elements: $ jq -c '.[-2:]' |
indices | $ jq -c 'keys' |
reverse | $ echo '[1,2,3]' | jq 'reverse' |
sort | $ echo '[3,1,4,2]' | jq 'sort' |
dedupe | $ echo '[1,1,2,3]' | jq 'unique' |
subset test | $ echo '[1,2,3]' | jq 'contains([1])' $ echo '[1]' | jq 'inside([1,2,3])' |
map | $ echo '[1,2,3]' | jq '.[] | . * .' $ echo '[1,2,3]' | jq 'map(. * .)' |
filter | $ echo '[1,2,3]' | jq 'map(select(. > 2))' |
reduce | $ echo '[1,2,3,4]'| jq 'reduce .[] as $item (0; .+$item)' |
universal and existential test | $ echo '[1,2,3]' | jq 'all(. > 2)' $ echo '[1,2,3]' | jq 'any(. > 2)' |
flatten one level, completely |
# flatten is new in 1.5: $ echo '[1,[2,[3]]]' | jq -c 'flatten(1)' $ echo '[1,[2,[3]]]' | jq -c 'flatten' |
dictionaries | |
jq | |
literal | {"t": 1, "f": 0} |
size | $ echo '{"t": 1, "f": 0}' | jq 'length' |
lookup | $ echo '{"t": 1, "f": 0}' | jq '.t' $ echo '{"t": 1, "f": 0}' | jq '.["t"]' |
update | $ echo '{"t": 1, "f": 0}' | jq '.f = -1' |
is key present | $ echo '{"t": 1, "f": 0}' | jq 'has("t")' $ echo '"t"' | jq 'in({"t": 1, "f": 0})' |
missing key behavior | # null: $ echo '{"t": 1, "f": 0}' | jq '.m' |
not a dictionary behavior | # error: $ echo 1 | jq '.foo' # no error and no output: $ echo 1 | jq '.foo?' |
delete | $ echo '{"t": 1, "f": 0}' | jq 'del(.t)' |
keys and values as arrays | $ echo '{"do": 1, "re": 2}' | jq 'keys' $ echo '{"do": 1, "re": 2}' | jq 'to_entries | map(.value)' |
functions | |
jq | |
define | $ echo '1 2 3 4' | jq 'def double: 2 * .;' |
call | $ echo '1 2 3 4' | jq 'def double: 2 * .; double' |
function with argument | $ echo '1 2 3 4' | jq 'def multiply($x): . * $x; multiply(7)' # without $, argument is treated as a filter: echo '1 2 3 4' | jq 'def apply(f): f; apply(. * 7)' |
execution control | |
jq | |
if | $ echo '-3' | jq 'if . < 0 then -. else . end' |
while | $ jq -n '1 | while(. < 10; . + 1)' |
break | $ jq -n '1 | label $out | while(true; if . > 10 then break $out else. + 1 end)' |
exceptions | |
jq | |
raise exception | $ jq -n 'error("bam!")' |
handle exception | # set output to null: $ jq -n 'try error("bam!") catch null' # two ways to handle with no output: $ jq -n 'try error("bam!") catch empty' $ jq -n 'error("bam!")?' |
streams | |
jq | |
write to stderr | # input to debug is also passed on to subsequent filters: $ jq -n '"foo" | debug' |
read input as array of strings | $ jq -R 'length' /etc/hosts |
array to stream | $ echo '[1,2,3]' | jq '.[]' |
stream to array | $ echo '1 2 3' | jq -s '.' |
file formats | |
jq | |
processes and environment | |
jq | |
environment variable | $ jq -n 'env.HOME' $ jq -n 'env["HOME"]' |
libraries and namespaces | |
jq | |
load library | $ cat > multiples.jq def double: 2 * .; def triple: 3 * .; def quadruple; 4 * .; $ echo 3 | jq 'include "multiples"; double' |
library path command line option | $ mkdir ~/.jq $ cat > ~/.jq/multiples.jq def double: 2 * .; def triple: 3 * .; def quadruple; 4 * .; $ echo 3 | jq -L ~/.jq 'include "multiples"; double' |
load definitions in namespace | $ cat > multiples.jq def double: 2 * .; def triple: 3 * .; def quadruple; 4 * .; $ echo 3 | jq 'import "multiples" as mult; mult::double' |
reflection | |
jq | |
inspect type | $ echo '{"foo": 1}' | jq '.foo | type' |
basic types | "number" "boolean" "array" "object" "null" "string" |
___________________________________________________________________ |