Extend jv_number to use decNumber for storing number literals. Any math operations on the numbers will truncate them to double precision. Comparisons when both numbers are literal numbers will compare them without truncation. Delay conversion of numbers to doubles until a math operation is performed, to preserve precision. A literal jv_number will only need conversion to double once, and will reuse the resultant double on subsequent conversions. Outputting literal jv_numbers preserves the original precision. Add strong pthread requirement to manage contexts/allocations for converting numbers between their decNumber, string, and double formats.
1715 lines
32 KiB
Plaintext
1715 lines
32 KiB
Plaintext
# Tests are groups of three lines: program, input, expected output
|
|
# Blank lines and lines starting with # are ignored
|
|
|
|
#
|
|
# Simple value tests to check parser. Input is irrelevant
|
|
#
|
|
|
|
true
|
|
null
|
|
true
|
|
|
|
false
|
|
null
|
|
false
|
|
|
|
null
|
|
42
|
|
null
|
|
|
|
1
|
|
null
|
|
1
|
|
|
|
|
|
-1
|
|
null
|
|
-1
|
|
|
|
# FIXME: much more number testing needed
|
|
|
|
{}
|
|
null
|
|
{}
|
|
|
|
[]
|
|
null
|
|
[]
|
|
|
|
{x: -1}
|
|
null
|
|
{"x": -1}
|
|
|
|
# The input line starts with a 0xFEFF (byte order mark) codepoint
|
|
# No, there is no reason to have a byte order mark in UTF8 text.
|
|
# But apparently people do, so jq shouldn't break on it.
|
|
.
|
|
"byte order mark"
|
|
"byte order mark"
|
|
|
|
# We test escapes by matching them against Unicode codepoints
|
|
# FIXME: more tests needed for weird unicode stuff (e.g. utf16 pairs)
|
|
"Aa\r\n\t\b\f\u03bc"
|
|
null
|
|
"Aa\u000d\u000a\u0009\u0008\u000c\u03bc"
|
|
|
|
.
|
|
"Aa\r\n\t\b\f\u03bc"
|
|
"Aa\u000d\u000a\u0009\u0008\u000c\u03bc"
|
|
|
|
"inter\("pol" + "ation")"
|
|
null
|
|
"interpolation"
|
|
|
|
@text,@json,([1,.] | (@csv, @tsv)),@html,@uri,@sh,@base64,(@base64 | @base64d)
|
|
"<>&'\"\t"
|
|
"<>&'\"\t"
|
|
"\"<>&'\\\"\\t\""
|
|
"1,\"<>&'\"\"\t\""
|
|
"1\t<>&'\"\\t"
|
|
"<>&'"\t"
|
|
"%3C%3E%26'%22%09"
|
|
"'<>&'\\''\"\t'"
|
|
"PD4mJyIJ"
|
|
"<>&'\"\t"
|
|
|
|
# regression test for #436
|
|
@base64
|
|
"foóbar\n"
|
|
"Zm/Ds2Jhcgo="
|
|
|
|
@base64d
|
|
"Zm/Ds2Jhcgo="
|
|
"foóbar\n"
|
|
|
|
@uri
|
|
"\u03bc"
|
|
"%CE%BC"
|
|
|
|
@html "<b>\(.)</b>"
|
|
"<script>hax</script>"
|
|
"<b><script>hax</script></b>"
|
|
|
|
[.[]|tojson|fromjson]
|
|
["foo", 1, ["a", 1, "b", 2, {"foo":"bar"}]]
|
|
["foo",1,["a",1,"b",2,{"foo":"bar"}]]
|
|
|
|
#
|
|
# Dictionary construction syntax
|
|
#
|
|
|
|
{a: 1}
|
|
null
|
|
{"a":1}
|
|
|
|
{a,b,(.d):.a,e:.b}
|
|
{"a":1, "b":2, "c":3, "d":"c"}
|
|
{"a":1, "b":2, "c":1, "e":2}
|
|
|
|
{"a",b,"a$\(1+1)"}
|
|
{"a":1, "b":2, "c":3, "a$2":4}
|
|
{"a":1, "b":2, "a$2":4}
|
|
|
|
%%FAIL
|
|
{(0):1}
|
|
jq: error: Cannot use number (0) as object key at <top-level>, line 1:
|
|
|
|
%%FAIL
|
|
{non_const:., (0):1}
|
|
jq: error: Cannot use number (0) as object key at <top-level>, line 1:
|
|
|
|
#
|
|
# Field access, piping
|
|
#
|
|
|
|
.foo
|
|
{"foo": 42, "bar": 43}
|
|
42
|
|
|
|
.foo | .bar
|
|
{"foo": {"bar": 42}, "bar": "badvalue"}
|
|
42
|
|
|
|
.foo.bar
|
|
{"foo": {"bar": 42}, "bar": "badvalue"}
|
|
42
|
|
|
|
.foo_bar
|
|
{"foo_bar": 2}
|
|
2
|
|
|
|
.["foo"].bar
|
|
{"foo": {"bar": 42}, "bar": "badvalue"}
|
|
42
|
|
|
|
."foo"."bar"
|
|
{"foo": {"bar": 20}}
|
|
20
|
|
|
|
[.[]|.foo?]
|
|
[1,[2],{"foo":3,"bar":4},{},{"foo":5}]
|
|
[3,null,5]
|
|
|
|
[.[]|.foo?.bar?]
|
|
[1,[2],[],{"foo":3},{"foo":{"bar":4}},{}]
|
|
[4,null]
|
|
|
|
[..]
|
|
[1,[[2]],{ "a":[1]}]
|
|
[[1,[[2]],{"a":[1]}],1,[[2]],[2],2,{"a":[1]},[1],1]
|
|
|
|
[.[]|.[]?]
|
|
[1,null,[],[1,[2,[[3]]]],[{}],[{"a":[1,[2]]}]]
|
|
[1,[2,[[3]]],{},{"a":[1,[2]]}]
|
|
|
|
[.[]|.[1:3]?]
|
|
[1,null,true,false,"abcdef",{},{"a":1,"b":2},[],[1,2,3,4,5],[1,2]]
|
|
[null,"bc",[],[2,3],[2]]
|
|
|
|
#
|
|
# Negative array indices
|
|
#
|
|
|
|
try (.foo[-1] = 0) catch .
|
|
null
|
|
"Out of bounds negative array index"
|
|
|
|
try (.foo[-2] = 0) catch .
|
|
null
|
|
"Out of bounds negative array index"
|
|
|
|
.[-1] = 5
|
|
[0,1,2]
|
|
[0,1,5]
|
|
|
|
.[-2] = 5
|
|
[0,1,2]
|
|
[0,5,2]
|
|
|
|
#
|
|
# Multiple outputs, iteration
|
|
#
|
|
|
|
.[]
|
|
[1,2,3]
|
|
1
|
|
2
|
|
3
|
|
|
|
1,1
|
|
[]
|
|
1
|
|
1
|
|
|
|
1,.
|
|
[]
|
|
1
|
|
[]
|
|
|
|
[.]
|
|
[2]
|
|
[[2]]
|
|
|
|
[[2]]
|
|
[3]
|
|
[[2]]
|
|
|
|
[{}]
|
|
[2]
|
|
[{}]
|
|
|
|
[.[]]
|
|
["a"]
|
|
["a"]
|
|
|
|
[(.,1),((.,.[]),(2,3))]
|
|
["a","b"]
|
|
[["a","b"],1,["a","b"],"a","b",2,3]
|
|
|
|
[([5,5][]),.,.[]]
|
|
[1,2,3]
|
|
[5,5,[1,2,3],1,2,3]
|
|
|
|
{x: (1,2)},{x:3} | .x
|
|
null
|
|
1
|
|
2
|
|
3
|
|
|
|
.[-2]
|
|
[1,2,3]
|
|
2
|
|
|
|
[range(0;10)]
|
|
null
|
|
[0,1,2,3,4,5,6,7,8,9]
|
|
|
|
[range(0,1;3,4)]
|
|
null
|
|
[0,1,2, 0,1,2,3, 1,2, 1,2,3]
|
|
|
|
[range(0;10;3)]
|
|
null
|
|
[0,3,6,9]
|
|
|
|
[range(0;10;-1)]
|
|
null
|
|
[]
|
|
|
|
[range(0;-5;-1)]
|
|
null
|
|
[0,-1,-2,-3,-4]
|
|
|
|
[range(0,1;4,5;1,2)]
|
|
null
|
|
[0,1,2,3,0,2, 0,1,2,3,4,0,2,4, 1,2,3,1,3, 1,2,3,4,1,3]
|
|
|
|
[while(.<100; .*2)]
|
|
1
|
|
[1,2,4,8,16,32,64]
|
|
|
|
[(label $here | .[] | if .>1 then break $here else . end), "hi!"]
|
|
[0,1,2]
|
|
[0,1,"hi!"]
|
|
|
|
[(label $here | .[] | if .>1 then break $here else . end), "hi!"]
|
|
[0,2,1]
|
|
[0,"hi!"]
|
|
|
|
%%FAIL
|
|
. as $foo | break $foo
|
|
jq: error: $*label-foo is not defined at <top-level>, line 1:
|
|
|
|
[.[]|[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]]
|
|
[1,2,3,4,5]
|
|
[1,2,6,24,120]
|
|
|
|
[label $out | foreach .[] as $item ([3, null]; if .[0] < 1 then break $out else [.[0] -1, $item] end; .[1])]
|
|
[11,22,33,44,55,66,77,88,99]
|
|
[11,22,33]
|
|
|
|
[foreach range(5) as $item (0; $item)]
|
|
null
|
|
[0,1,2,3,4]
|
|
|
|
[foreach .[] as [$i, $j] (0; . + $i - $j)]
|
|
[[2,1], [5,3], [6,4]]
|
|
[1,3,5]
|
|
|
|
[foreach .[] as {a:$a} (0; . + $a; -.)]
|
|
[{"a":1}, {"b":2}, {"a":3, "b":4}]
|
|
[-1, -1, -4]
|
|
|
|
[limit(3; .[])]
|
|
[11,22,33,44,55,66,77,88,99]
|
|
[11,22,33]
|
|
|
|
[limit(0; error)]
|
|
"badness"
|
|
[]
|
|
|
|
[limit(1; 1, error)]
|
|
"badness"
|
|
[1]
|
|
|
|
[first(range(.)), last(range(.)), nth(0; range(.)), nth(5; range(.)), try nth(-1; range(.)) catch .]
|
|
10
|
|
[0,9,0,5,"nth doesn't support negative indices"]
|
|
|
|
# Check that first(g) does not extract more than one value from g
|
|
first(1,error("foo"))
|
|
null
|
|
1
|
|
|
|
#
|
|
# Check that various builtins evalute all arguments where appropriate,
|
|
# doing cartesian products where appropriate.
|
|
#
|
|
|
|
# Check that limit does work for each value produced by n!
|
|
[limit(5,7; range(9))]
|
|
null
|
|
[0,1,2,3,4,0,1,2,3,4,5,6]
|
|
|
|
# Same check for nth
|
|
[nth(5,7; range(9;0;-1))]
|
|
null
|
|
[4,2]
|
|
|
|
# Same check for range/3
|
|
[range(0,1,2;4,3,2;2,3)]
|
|
null
|
|
[0,2,0,3,0,2,0,0,0,1,3,1,1,1,1,1,2,2,2,2]
|
|
|
|
# Same check for range/1
|
|
[range(3,5)]
|
|
null
|
|
[0,1,2,0,1,2,3,4]
|
|
|
|
# Same check for index/1, rindex/1, indices/1
|
|
[(index(",","|"), rindex(",","|")), indices(",","|")]
|
|
"a,b|c,d,e||f,g,h,|,|,i,j"
|
|
[1,3,22,19,[1,5,7,12,14,16,18,20,22],[3,9,10,17,19]]
|
|
|
|
# Same check for join/1
|
|
join(",","/")
|
|
["a","b","c","d"]
|
|
"a,b,c,d"
|
|
"a/b/c/d"
|
|
|
|
[.[]|join("a")]
|
|
[[],[""],["",""],["","",""]]
|
|
["","","a","aa"]
|
|
|
|
# Same check for flatten/1
|
|
flatten(3,2,1)
|
|
[0, [1], [[2]], [[[3]]]]
|
|
[0,1,2,3]
|
|
[0,1,2,[3]]
|
|
[0,1,[2],[[3]]]
|
|
|
|
|
|
#
|
|
# Slices
|
|
#
|
|
|
|
[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]
|
|
[0,1,2,3,4,5,6]
|
|
[[], [2,3], [0,1,2,3,4], [5,6], [], []]
|
|
|
|
[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]
|
|
"abcdefghi"
|
|
["","","abcdefg","hi","",""]
|
|
|
|
del(.[2:4],.[0],.[-2:])
|
|
[0,1,2,3,4,5,6,7]
|
|
[1,4,5]
|
|
|
|
.[2:4] = ([], ["a","b"], ["a","b","c"])
|
|
[0,1,2,3,4,5,6,7]
|
|
[0,1,4,5,6,7]
|
|
[0,1,"a","b",4,5,6,7]
|
|
[0,1,"a","b","c",4,5,6,7]
|
|
|
|
# Slices at large offsets (issue #1108)
|
|
#
|
|
# This is written this way because [range(<large number>)] is
|
|
# significantly slower under valgrind than .[<large number>] = value.
|
|
#
|
|
# We range down rather than up so that we have just one realloc.
|
|
reduce range(65540;65536;-1) as $i ([]; .[$i] = $i)|.[65536:]
|
|
null
|
|
[null,65537,65538,65539,65540]
|
|
|
|
#
|
|
# Variables
|
|
#
|
|
|
|
1 as $x | 2 as $y | [$x,$y,$x]
|
|
null
|
|
[1,2,1]
|
|
|
|
[1,2,3][] as $x | [[4,5,6,7][$x]]
|
|
null
|
|
[5]
|
|
[6]
|
|
[7]
|
|
|
|
42 as $x | . | . | . + 432 | $x + 1
|
|
34324
|
|
43
|
|
|
|
1 as $x | [$x,$x,$x as $x | $x]
|
|
null
|
|
[1,1,1]
|
|
|
|
[1, {c:3, d:4}] as [$a, {c:$b, b:$c}] | $a, $b, $c
|
|
null
|
|
1
|
|
3
|
|
null
|
|
|
|
. as {as: $kw, "str": $str, ("e"+"x"+"p"): $exp} | [$kw, $str, $exp]
|
|
{"as": 1, "str": 2, "exp": 3}
|
|
[1, 2, 3]
|
|
|
|
.[] as [$a, $b] | [$b, $a]
|
|
[[1], [1, 2, 3]]
|
|
[null, 1]
|
|
[2, 1]
|
|
|
|
. as $i | . as [$i] | $i
|
|
[0]
|
|
0
|
|
|
|
. as [$i] | . as $i | $i
|
|
[0]
|
|
[0]
|
|
|
|
%%FAIL IGNORE MSG
|
|
. as [] | null
|
|
jq: error: syntax error, unexpected ']', expecting '$' or '[' or '{' (Unix shell quoting issues?) at <top-level>, line 1:
|
|
|
|
%%FAIL IGNORE MSG
|
|
. as {} | null
|
|
jq: error: syntax error, unexpected '}' (Unix shell quoting issues?) at <top-level>, line 1:
|
|
|
|
# [.,(.[] | {x:.},.),.,.[]]
|
|
|
|
#
|
|
# Builtin functions
|
|
#
|
|
|
|
1+1
|
|
null
|
|
2
|
|
|
|
1+1
|
|
"wtasdf"
|
|
2.0
|
|
|
|
2-1
|
|
null
|
|
1
|
|
|
|
2-(-1)
|
|
null
|
|
3
|
|
|
|
1e+0+0.001e3
|
|
"I wonder what this will be?"
|
|
20e-1
|
|
|
|
.+4
|
|
15
|
|
19.0
|
|
|
|
.+null
|
|
{"a":42}
|
|
{"a":42}
|
|
|
|
null+.
|
|
null
|
|
null
|
|
|
|
.a+.b
|
|
{"a":42}
|
|
42
|
|
|
|
[1,2,3] + [.]
|
|
null
|
|
[1,2,3,null]
|
|
|
|
{"a":1} + {"b":2} + {"c":3}
|
|
"asdfasdf"
|
|
{"a":1, "b":2, "c":3}
|
|
|
|
"asdf" + "jkl;" + . + . + .
|
|
"some string"
|
|
"asdfjkl;some stringsome stringsome string"
|
|
|
|
"\u0000\u0020\u0000" + .
|
|
"\u0000\u0020\u0000"
|
|
"\u0000 \u0000\u0000 \u0000"
|
|
|
|
42 - .
|
|
11
|
|
31
|
|
|
|
[1,2,3,4,1] - [.,3]
|
|
1
|
|
[2,4]
|
|
|
|
[10 * 20, 20 / .]
|
|
4
|
|
[200, 5]
|
|
|
|
1 + 2 * 2 + 10 / 2
|
|
null
|
|
10
|
|
|
|
[16 / 4 / 2, 16 / 4 * 2, 16 - 4 - 2, 16 - 4 + 2]
|
|
null
|
|
[2, 8, 10, 14]
|
|
|
|
25 % 7
|
|
null
|
|
4
|
|
|
|
49732 % 472
|
|
null
|
|
172
|
|
|
|
1 + tonumber + ("10" | tonumber)
|
|
4
|
|
15
|
|
|
|
[{"a":42},.object,10,.num,false,true,null,"b",[1,4]] | .[] as $x | [$x == .[]]
|
|
{"object": {"a":42}, "num":10.0}
|
|
[true, true, false, false, false, false, false, false, false]
|
|
[true, true, false, false, false, false, false, false, false]
|
|
[false, false, true, true, false, false, false, false, false]
|
|
[false, false, true, true, false, false, false, false, false]
|
|
[false, false, false, false, true, false, false, false, false]
|
|
[false, false, false, false, false, true, false, false, false]
|
|
[false, false, false, false, false, false, true, false, false]
|
|
[false, false, false, false, false, false, false, true, false]
|
|
[false, false, false, false, false, false, false, false, true ]
|
|
|
|
[.[] | length]
|
|
[[], {}, [1,2], {"a":42}, "asdf", "\u03bc"]
|
|
[0, 0, 2, 1, 4, 1]
|
|
|
|
utf8bytelength
|
|
"asdf\u03bc"
|
|
6
|
|
|
|
[.[] | try utf8bytelength catch .]
|
|
[[], {}, [1,2], 55, true, false]
|
|
["array ([]) only strings have UTF-8 byte length","object ({}) only strings have UTF-8 byte length","array ([1,2]) only strings have UTF-8 byte length","number (55) only strings have UTF-8 byte length","boolean (true) only strings have UTF-8 byte length","boolean (false) only strings have UTF-8 byte length"]
|
|
|
|
|
|
map(keys)
|
|
[{}, {"abcd":1,"abc":2,"abcde":3}, {"x":1, "z": 3, "y":2}]
|
|
[[], ["abc","abcd","abcde"], ["x","y","z"]]
|
|
|
|
[1,2,empty,3,empty,4]
|
|
null
|
|
[1,2,3,4]
|
|
|
|
map(add)
|
|
[[], [1,2,3], ["a","b","c"], [[3],[4,5],[6]], [{"a":1}, {"b":2}, {"a":3}]]
|
|
[null, 6, "abc", [3,4,5,6], {"a":3, "b": 2}]
|
|
|
|
map_values(.+1)
|
|
[0,1,2]
|
|
[1,2,3]
|
|
|
|
#
|
|
# User-defined functions
|
|
# Oh god.
|
|
#
|
|
|
|
def f: . + 1; def g: def g: . + 100; f | g | f; (f | g), g
|
|
3.0
|
|
106.0
|
|
105.0
|
|
|
|
def f: (1000,2000); f
|
|
123412345
|
|
1000
|
|
2000
|
|
|
|
def f(a;b;c;d;e;f): [a+1,b,c,d,e,f]; f(.[0];.[1];.[0];.[0];.[0];.[0])
|
|
[1,2]
|
|
[2,2,1,1,1,1]
|
|
|
|
def f: 1; def g: f, def f: 2; def g: 3; f, def f: g; f, g; def f: 4; [f, def f: g; def g: 5; f, g]+[f,g]
|
|
null
|
|
[4,1,2,3,3,5,4,1,2,3,3]
|
|
|
|
# Test precedence of 'def' vs '|'
|
|
def a: 0; . | a
|
|
null
|
|
0
|
|
|
|
# Many arguments
|
|
def f(a;b;c;d;e;f;g;h;i;j): [j,i,h,g,f,e,d,c,b,a]; f(.[0];.[1];.[2];.[3];.[4];.[5];.[6];.[7];.[8];.[9])
|
|
[0,1,2,3,4,5,6,7,8,9]
|
|
[9,8,7,6,5,4,3,2,1,0]
|
|
|
|
([1,2] + [4,5])
|
|
[1,2,3]
|
|
[1,2,4,5]
|
|
|
|
true
|
|
[1]
|
|
true
|
|
|
|
null,1,null
|
|
"hello"
|
|
null
|
|
1
|
|
null
|
|
|
|
[1,2,3]
|
|
[5,6]
|
|
[1,2,3]
|
|
|
|
[.[]|floor]
|
|
[-1.1,1.1,1.9]
|
|
[-2, 1, 1]
|
|
|
|
[.[]|sqrt]
|
|
[4,9]
|
|
[2,3]
|
|
|
|
(add / length) as $m | map((. - $m) as $d | $d * $d) | add / length | sqrt
|
|
[2,4,4,4,5,5,7,9]
|
|
2
|
|
|
|
# Should write a test that calls the -lm function from C (or bc(1)) to
|
|
# check that they match the corresponding jq functions. However,
|
|
# there's so little template code standing between that it suffices to
|
|
# test a handful of these. The results were checked by eye against
|
|
# bc(1).
|
|
atan * 4 * 1000000|floor / 1000000
|
|
1
|
|
3.141592
|
|
|
|
[(3.141592 / 2) * (range(0;20) / 20)|cos * 1000000|floor / 1000000]
|
|
null
|
|
[1,0.996917,0.987688,0.972369,0.951056,0.923879,0.891006,0.85264,0.809017,0.760406,0.707106,0.649448,0.587785,0.522498,0.45399,0.382683,0.309017,0.233445,0.156434,0.078459]
|
|
|
|
[(3.141592 / 2) * (range(0;20) / 20)|sin * 1000000|floor / 1000000]
|
|
null
|
|
[0,0.078459,0.156434,0.233445,0.309016,0.382683,0.45399,0.522498,0.587785,0.649447,0.707106,0.760405,0.809016,0.85264,0.891006,0.923879,0.951056,0.972369,0.987688,0.996917]
|
|
|
|
|
|
def f(x): x | x; f([.], . + [42])
|
|
[1,2,3]
|
|
[[[1,2,3]]]
|
|
[[1,2,3],42]
|
|
[[1,2,3,42]]
|
|
[1,2,3,42,42]
|
|
|
|
# test multiple function arities and redefinition
|
|
def f: .+1; def g: f; def f: .+100; def f(a):a+.+11; [(g|f(20)), f]
|
|
1
|
|
[33,101]
|
|
|
|
# test closures and lexical scoping
|
|
def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x | f($x,$x+x); g($x)
|
|
"more testing"
|
|
[1,100,2100.0,100,2100.0]
|
|
|
|
# test def f($a) syntax
|
|
def x(a;b): a as $a | b as $b | $a + $b; def y($a;$b): $a + $b; def check(a;b): [x(a;b)] == [y(a;b)]; check(.[];.[]*2)
|
|
[1,2,3]
|
|
true
|
|
|
|
# test backtracking through function calls and returns
|
|
# this test is *evil*
|
|
[[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]
|
|
999999999
|
|
[[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]
|
|
|
|
# test recursion
|
|
def fac: if . == 1 then 1 else . * (. - 1 | fac) end; [.[] | fac]
|
|
[1,2,3,4]
|
|
[1,2,6,24]
|
|
|
|
# test stack overflow and reallocation
|
|
# this test is disabled for now, it takes a realllllly long time.
|
|
# def f: if length > 1000 then . else .+[1]|f end; f | length
|
|
# []
|
|
# 1001
|
|
|
|
reduce .[] as $x (0; . + $x)
|
|
[1,2,4]
|
|
7
|
|
|
|
reduce .[] as [$i, {j:$j}] (0; . + $i - $j)
|
|
[[2,{"j":1}], [5,{"j":3}], [6,{"j":4}]]
|
|
5
|
|
|
|
reduce [[1,2,10], [3,4,10]][] as [$i,$j] (0; . + $i * $j)
|
|
null
|
|
14
|
|
|
|
# This, while useless, should still compile.
|
|
reduce . as $n (.; .)
|
|
null
|
|
null
|
|
|
|
# Destructuring
|
|
. as {$a, b: [$c, {$d}]} | [$a, $c, $d]
|
|
{"a":1, "b":[2,{"d":3}]}
|
|
[1,2,3]
|
|
|
|
. as {$a, $b:[$c, $d]}| [$a, $b, $c, $d]
|
|
{"a":1, "b":[2,{"d":3}]}
|
|
[1,[2,{"d":3}],2,{"d":3}]
|
|
|
|
# Destructuring with alternation
|
|
.[] | . as {$a, b: [$c, {$d}]} ?// [$a, {$b}, $e] ?// $f | [$a, $b, $c, $d, $e, $f]
|
|
[{"a":1, "b":[2,{"d":3}]}, [4, {"b":5, "c":6}, 7, 8, 9], "foo"]
|
|
[1, null, 2, 3, null, null]
|
|
[4, 5, null, null, 7, null]
|
|
[null, null, null, null, null, "foo"]
|
|
|
|
# Destructuring DUP/POP issues
|
|
.[] | . as {a:$a} ?// {a:$a} ?// {a:$a} | $a
|
|
[[3],[4],[5],6]
|
|
# Runtime error: "jq: Cannot index array with string \"c\""
|
|
|
|
.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
|
|
[[3],[4],[5],6]
|
|
# Runtime error: "jq: Cannot index array with string \"c\""
|
|
|
|
[[3],[4],[5],6][] | . as {a:$a} ?// {a:$a} ?// {a:$a} | $a
|
|
null
|
|
# Runtime error: "jq: Cannot index array with string \"c\""
|
|
|
|
[[3],[4],[5],6] | .[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
|
|
null
|
|
# Runtime error: "jq: Cannot index array with string \"c\""
|
|
|
|
.[] | . as {a:$a} ?// {a:$a} ?// $a | $a
|
|
[[3],[4],[5],6]
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
.[] as {a:$a} ?// {a:$a} ?// $a | $a
|
|
[[3],[4],[5],6]
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
[[3],[4],[5],6][] | . as {a:$a} ?// {a:$a} ?// $a | $a
|
|
null
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
[[3],[4],[5],6] | .[] as {a:$a} ?// {a:$a} ?// $a | $a
|
|
null
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
.[] | . as {a:$a} ?// $a ?// {a:$a} | $a
|
|
[[3],[4],[5],6]
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
.[] as {a:$a} ?// $a ?// {a:$a} | $a
|
|
[[3],[4],[5],6]
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
[[3],[4],[5],6][] | . as {a:$a} ?// $a ?// {a:$a} | $a
|
|
null
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
[[3],[4],[5],6] | .[] as {a:$a} ?// $a ?// {a:$a} | $a
|
|
null
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
.[] | . as $a ?// {a:$a} ?// {a:$a} | $a
|
|
[[3],[4],[5],6]
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
.[] as $a ?// {a:$a} ?// {a:$a} | $a
|
|
[[3],[4],[5],6]
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
[[3],[4],[5],6][] | . as $a ?// {a:$a} ?// {a:$a} | $a
|
|
null
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
[[3],[4],[5],6] | .[] as $a ?// {a:$a} ?// {a:$a} | $a
|
|
null
|
|
[3]
|
|
[4]
|
|
[5]
|
|
6
|
|
|
|
. as $dot|any($dot[];not)
|
|
[1,2,3,4,true,false,1,2,3,4,5]
|
|
true
|
|
|
|
. as $dot|any($dot[];not)
|
|
[1,2,3,4,true]
|
|
false
|
|
|
|
. as $dot|all($dot[];.)
|
|
[1,2,3,4,true,false,1,2,3,4,5]
|
|
false
|
|
|
|
. as $dot|all($dot[];.)
|
|
[1,2,3,4,true]
|
|
true
|
|
|
|
# Check short-circuiting
|
|
any(true, error; .)
|
|
"badness"
|
|
true
|
|
|
|
all(false, error; .)
|
|
"badness"
|
|
false
|
|
|
|
any(not)
|
|
[]
|
|
false
|
|
|
|
all(not)
|
|
[]
|
|
true
|
|
|
|
any(not)
|
|
[false]
|
|
true
|
|
|
|
all(not)
|
|
[false]
|
|
true
|
|
|
|
[any,all]
|
|
[]
|
|
[false,true]
|
|
|
|
[any,all]
|
|
[true]
|
|
[true,true]
|
|
|
|
[any,all]
|
|
[false]
|
|
[false,false]
|
|
|
|
[any,all]
|
|
[true,false]
|
|
[true,false]
|
|
|
|
[any,all]
|
|
[null,null,true]
|
|
[true,false]
|
|
|
|
#
|
|
# Paths
|
|
#
|
|
|
|
path(.foo[0,1])
|
|
null
|
|
["foo", 0]
|
|
["foo", 1]
|
|
|
|
path(.[] | select(.>3))
|
|
[1,5,3]
|
|
[1]
|
|
|
|
path(.)
|
|
42
|
|
[]
|
|
|
|
try path(.a | map(select(.b == 0))) catch .
|
|
{"a":[{"b":0}]}
|
|
"Invalid path expression with result [{\"b\":0}]"
|
|
|
|
try path(.a | map(select(.b == 0)) | .[0]) catch .
|
|
{"a":[{"b":0}]}
|
|
"Invalid path expression near attempt to access element 0 of [{\"b\":0}]"
|
|
|
|
try path(.a | map(select(.b == 0)) | .c) catch .
|
|
{"a":[{"b":0}]}
|
|
"Invalid path expression near attempt to access element \"c\" of [{\"b\":0}]"
|
|
|
|
try path(.a | map(select(.b == 0)) | .[]) catch .
|
|
{"a":[{"b":0}]}
|
|
"Invalid path expression near attempt to iterate through [{\"b\":0}]"
|
|
|
|
path(.a[path(.b)[0]])
|
|
{"a":{"b":0}}
|
|
["a","b"]
|
|
|
|
[paths]
|
|
[1,[[],{"a":2}]]
|
|
[[0],[1],[1,0],[1,1],[1,1,"a"]]
|
|
|
|
[leaf_paths]
|
|
[1,[[],{"a":2}]]
|
|
[[0],[1,1,"a"]]
|
|
|
|
["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])
|
|
{"bar": 42, "foo": ["a", "b", "c", "d"]}
|
|
"b"
|
|
{"bar": 42, "foo": ["a", 20, "c", "d"]}
|
|
{"bar": 42, "foo": ["a", "c", "d"]}
|
|
|
|
map(getpath([2])), map(setpath([2]; 42)), map(delpaths([[2]]))
|
|
[[0], [0,1], [0,1,2]]
|
|
[null, null, 2]
|
|
[[0,null,42], [0,1,42], [0,1,42]]
|
|
[[0], [0,1], [0,1]]
|
|
|
|
map(delpaths([[0,"foo"]]))
|
|
[[{"foo":2, "x":1}], [{"bar":2}]]
|
|
[[{"x":1}], [{"bar":2}]]
|
|
|
|
["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])
|
|
{"bar":false}
|
|
null
|
|
{"bar":false, "foo": [null, 20]}
|
|
{"bar":false}
|
|
|
|
delpaths([[-200]])
|
|
[1,2,3]
|
|
[1,2,3]
|
|
|
|
try delpaths(0) catch .
|
|
{}
|
|
"Paths must be specified as an array"
|
|
|
|
del(.), del(empty), del((.foo,.bar,.baz) | .[2,3,0]), del(.foo[0], .bar[0], .foo, .baz.bar[0].x)
|
|
{"foo": [0,1,2,3,4], "bar": [0,1]}
|
|
null
|
|
{"foo": [0,1,2,3,4], "bar": [0,1]}
|
|
{"foo": [1,4], "bar": [1]}
|
|
{"bar": [1]}
|
|
|
|
del(.[1], .[-6], .[2], .[-3:9])
|
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
[0, 3, 5, 6, 9]
|
|
|
|
#
|
|
# Assignment
|
|
#
|
|
.message = "goodbye"
|
|
{"message": "hello"}
|
|
{"message": "goodbye"}
|
|
|
|
.foo = .bar
|
|
{"bar":42}
|
|
{"foo":42, "bar":42}
|
|
|
|
.foo |= .+1
|
|
{"foo": 42}
|
|
{"foo": 43}
|
|
|
|
.[] += 2, .[] *= 2, .[] -= 2, .[] /= 2, .[] %=2
|
|
[1,3,5]
|
|
[3,5,7]
|
|
[2,6,10]
|
|
[-1,1,3]
|
|
[0.5, 1.5, 2.5]
|
|
[1,1,1]
|
|
|
|
[.[] % 7]
|
|
[-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7]
|
|
[0,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,0]
|
|
|
|
.foo += .foo
|
|
{"foo":2}
|
|
{"foo":4}
|
|
|
|
.[0].a |= {"old":., "new":(.+1)}
|
|
[{"a":1,"b":2}]
|
|
[{"a":{"old":1, "new":2},"b":2}]
|
|
|
|
def inc(x): x |= .+1; inc(.[].a)
|
|
[{"a":1,"b":2},{"a":2,"b":4},{"a":7,"b":8}]
|
|
[{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}]
|
|
|
|
# #1358, getpath/1 should work in path expressions
|
|
.[] | try (getpath(["a",0,"b"]) |= 5) catch .
|
|
[null,{"b":0},{"a":0},{"a":null},{"a":[0,1]},{"a":{"b":1}},{"a":[{}]},{"a":[{"c":3}]}]
|
|
{"a":[{"b":5}]}
|
|
{"b":0,"a":[{"b":5}]}
|
|
"Cannot index number with number"
|
|
{"a":[{"b":5}]}
|
|
"Cannot index number with string \"b\""
|
|
"Cannot index object with number"
|
|
{"a":[{"b":5}]}
|
|
{"a":[{"c":3,"b":5}]}
|
|
|
|
.[2][3] = 1
|
|
[4]
|
|
[4, null, [null, null, null, 1]]
|
|
|
|
.foo[2].bar = 1
|
|
{"foo":[11], "bar":42}
|
|
{"foo":[11,null,{"bar":1}], "bar":42}
|
|
|
|
try ((map(select(.a == 1))[].b) = 10) catch .
|
|
[{"a":0},{"a":1}]
|
|
"Invalid path expression near attempt to iterate through [{\"a\":1}]"
|
|
|
|
try ((map(select(.a == 1))[].a) |= .+1) catch .
|
|
[{"a":0},{"a":1}]
|
|
"Invalid path expression near attempt to iterate through [{\"a\":1}]"
|
|
|
|
def x: .[1,2]; x=10
|
|
[0,1,2]
|
|
[0,10,10]
|
|
|
|
try (def x: reverse; x=10) catch .
|
|
[0,1,2]
|
|
"Invalid path expression with result [2,1,0]"
|
|
|
|
.[] = 1
|
|
[1,null,Infinity,-Infinity,NaN,-NaN]
|
|
[1,1,1,1,1,1]
|
|
|
|
#
|
|
# Conditionals
|
|
#
|
|
|
|
[.[] | if .foo then "yep" else "nope" end]
|
|
[{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}]
|
|
["yep","yep","yep","yep","nope","nope","yep","nope"]
|
|
|
|
[.[] | if .baz then "strange" elif .foo then "yep" else "nope" end]
|
|
[{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}]
|
|
["yep","yep","yep","yep","nope","nope","yep","nope"]
|
|
|
|
[if 1,null,2 then 3 else 4 end]
|
|
null
|
|
[3,4,3]
|
|
|
|
[if empty then 3 else 4 end]
|
|
null
|
|
[]
|
|
|
|
[if 1 then 3,4 else 5 end]
|
|
null
|
|
[3,4]
|
|
|
|
[if null then 3 else 5,6 end]
|
|
null
|
|
[5,6]
|
|
|
|
[if true then 3 end]
|
|
7
|
|
[3]
|
|
|
|
[if false then 3 end]
|
|
7
|
|
[7]
|
|
|
|
[if false then 3 else . end]
|
|
7
|
|
[7]
|
|
|
|
|
|
[.[] | [.foo[] // .bar]]
|
|
[{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]
|
|
[[1,2], [1], [3], [42], [41]]
|
|
|
|
.[] //= .[0]
|
|
["hello",true,false,[false],null]
|
|
["hello",true,"hello",[false],"hello"]
|
|
|
|
.[] | [.[0] and .[1], .[0] or .[1]]
|
|
[[true,[]], [false,1], [42,null], [null,false]]
|
|
[true,true]
|
|
[false,true]
|
|
[false,true]
|
|
[false,false]
|
|
|
|
[.[] | not]
|
|
[1,0,false,null,true,"hello"]
|
|
[false,false,true,true,false,false]
|
|
|
|
# Check numeric comparison binops
|
|
[10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20]
|
|
{}
|
|
[true,false,false,false,false,true]
|
|
|
|
[10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20]
|
|
{}
|
|
[true,true,false,false,true,true]
|
|
|
|
# And some in/equality tests
|
|
[ 10 == 10, 10 != 10, 10 != 11, 10 == 11]
|
|
{}
|
|
[true,false,true,false]
|
|
|
|
["hello" == "hello", "hello" != "hello", "hello" == "world", "hello" != "world" ]
|
|
{}
|
|
[true,false,false,true]
|
|
|
|
[[1,2,3] == [1,2,3], [1,2,3] != [1,2,3], [1,2,3] == [4,5,6], [1,2,3] != [4,5,6]]
|
|
{}
|
|
[true,false,false,true]
|
|
|
|
[{"foo":42} == {"foo":42},{"foo":42} != {"foo":42}, {"foo":42} != {"bar":42}, {"foo":42} == {"bar":42}]
|
|
{}
|
|
[true,false,true,false]
|
|
|
|
# ugly complicated thing
|
|
[{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":18},"world"]},{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":19},"world"]}]
|
|
{}
|
|
[true,false]
|
|
|
|
# containment operator
|
|
[("foo" | contains("foo")), ("foobar" | contains("foo")), ("foo" | contains("foobar"))]
|
|
{}
|
|
[true, true, false]
|
|
|
|
# containment operator (embedded NULs!)
|
|
[contains(""), contains("\u0000")]
|
|
"\u0000"
|
|
[true, true]
|
|
|
|
[contains(""), contains("a"), contains("ab"), contains("c"), contains("d")]
|
|
"ab\u0000cd"
|
|
[true, true, true, true, true]
|
|
|
|
[contains("cd"), contains("b\u0000"), contains("ab\u0000")]
|
|
"ab\u0000cd"
|
|
[true, true, true]
|
|
|
|
[contains("b\u0000c"), contains("b\u0000cd"), contains("b\u0000cd")]
|
|
"ab\u0000cd"
|
|
[true, true, true]
|
|
|
|
[contains("@"), contains("\u0000@"), contains("\u0000what")]
|
|
"ab\u0000cd"
|
|
[false, false, false]
|
|
|
|
|
|
# Try/catch and general `?` operator
|
|
[.[]|try if . == 0 then error("foo") elif . == 1 then .a elif . == 2 then empty else . end catch .]
|
|
[0,1,2,3]
|
|
["foo","Cannot index number with string \"a\"",3]
|
|
|
|
[.[]|(.a, .a)?]
|
|
[null,true,{"a":1}]
|
|
[null,null,1,1]
|
|
|
|
[[.[]|[.a,.a]]?]
|
|
[null,true,{"a":1}]
|
|
[]
|
|
|
|
try error("\($__loc__)") catch .
|
|
null
|
|
"{\"file\":\"<top-level>\",\"line\":1}"
|
|
|
|
# string operations
|
|
[.[]|startswith("foo")]
|
|
["fo", "foo", "barfoo", "foobar", "barfoob"]
|
|
[false, true, false, true, false]
|
|
|
|
[.[]|endswith("foo")]
|
|
["fo", "foo", "barfoo", "foobar", "barfoob"]
|
|
[false, true, true, false, false]
|
|
|
|
[.[] | split(", ")]
|
|
["a,b, c, d, e,f",", a,b, c, d, e,f, "]
|
|
[["a,b","c","d","e,f"],["","a,b","c","d","e,f",""]]
|
|
|
|
split("")
|
|
"abc"
|
|
["a","b","c"]
|
|
|
|
[.[]|ltrimstr("foo")]
|
|
["fo", "foo", "barfoo", "foobar", "afoo"]
|
|
["fo","","barfoo","bar","afoo"]
|
|
|
|
[.[]|rtrimstr("foo")]
|
|
["fo", "foo", "barfoo", "foobar", "foob"]
|
|
["fo","","bar","foobar","foob"]
|
|
|
|
[(index(","), rindex(",")), indices(",")]
|
|
"a,bc,def,ghij,klmno"
|
|
[1,13,[1,4,8,13]]
|
|
|
|
indices(1)
|
|
[0,1,1,2,3,4,1,5]
|
|
[1,2,6]
|
|
|
|
indices([1,2])
|
|
[0,1,2,3,1,4,2,5,1,2,6,7]
|
|
[1,8]
|
|
|
|
indices([1,2])
|
|
[1]
|
|
[]
|
|
|
|
indices(", ")
|
|
"a,b, cd,e, fgh, ijkl"
|
|
[3,9,14]
|
|
|
|
[.[]|split(",")]
|
|
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
|
|
[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]
|
|
|
|
[.[]|split(", ")]
|
|
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
|
|
[["a","bc","def","ghij","jklmn","a,b","c,d","e,f"],["a,b,c,d","e,f,g,h"]]
|
|
|
|
[.[] * 3]
|
|
["a", "ab", "abc"]
|
|
["aaa", "ababab", "abcabcabc"]
|
|
|
|
[.[] / ","]
|
|
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
|
|
[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]
|
|
|
|
[.[] / ", "]
|
|
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
|
|
[["a","bc","def","ghij","jklmn","a,b","c,d","e,f"],["a,b,c,d","e,f,g,h"]]
|
|
|
|
map(.[1] as $needle | .[0] | contains($needle))
|
|
[[[],[]], [[1,2,3], [1,2]], [[1,2,3], [3,1]], [[1,2,3], [4]], [[1,2,3], [1,4]]]
|
|
[true, true, true, false, false]
|
|
|
|
map(.[1] as $needle | .[0] | contains($needle))
|
|
[[["foobar", "foobaz"], ["baz", "bar"]], [["foobar", "foobaz"], ["foo"]], [["foobar", "foobaz"], ["blap"]]]
|
|
[true, true, false]
|
|
|
|
[({foo: 12, bar:13} | contains({foo: 12})), ({foo: 12} | contains({})), ({foo: 12, bar:13} | contains({baz:14}))]
|
|
{}
|
|
[true, true, false]
|
|
|
|
{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {}}})
|
|
{}
|
|
true
|
|
|
|
{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {bar: 14}}})
|
|
{}
|
|
false
|
|
|
|
sort
|
|
[42,[2,5,3,11],10,{"a":42,"b":2},{"a":42},true,2,[2,6],"hello",null,[2,5,6],{"a":[],"b":1},"abc","ab",[3,10],{},false,"abcd",null]
|
|
[null,null,false,true,2,10,42,"ab","abc","abcd","hello",[2,5,3,11],[2,5,6],[2,6],[3,10],{},{"a":42},{"a":42,"b":2},{"a":[],"b":1}]
|
|
|
|
(sort_by(.b) | sort_by(.a)), sort_by(.a, .b), sort_by(.b, .c), group_by(.b), group_by(.a + .b - .c == 2)
|
|
[{"a": 1, "b": 4, "c": 14}, {"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}, {"a": 0, "b": 2, "c": 43}]
|
|
[{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}]
|
|
[{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}]
|
|
[{"a": 4, "b": 1, "c": 3}, {"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 3}, {"a": 1, "b": 4, "c": 14}]
|
|
[[{"a": 4, "b": 1, "c": 3}], [{"a": 0, "b": 2, "c": 43}], [{"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}]]
|
|
[[{"a": 1, "b": 4, "c": 14}, {"a": 0, "b": 2, "c": 43}], [{"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}]]
|
|
|
|
unique
|
|
[1,2,5,3,5,3,1,3]
|
|
[1,2,3,5]
|
|
|
|
unique
|
|
[]
|
|
[]
|
|
|
|
[min, max, min_by(.[1]), max_by(.[1]), min_by(.[2]), max_by(.[2])]
|
|
[[4,2,"a"],[3,1,"a"],[2,4,"a"],[1,3,"a"]]
|
|
[[1,3,"a"],[4,2,"a"],[3,1,"a"],[2,4,"a"],[4,2,"a"],[1,3,"a"]]
|
|
|
|
[min,max,min_by(.),max_by(.)]
|
|
[]
|
|
[null,null,null,null]
|
|
|
|
.foo[.baz]
|
|
{"foo":{"bar":4},"baz":"bar"}
|
|
4
|
|
|
|
.[] | .error = "no, it's OK"
|
|
[{"error":true}]
|
|
{"error": "no, it's OK"}
|
|
|
|
[{a:1}] | .[] | .a=999
|
|
null
|
|
{"a": 999}
|
|
|
|
to_entries
|
|
{"a": 1, "b": 2}
|
|
[{"key":"a", "value":1}, {"key":"b", "value":2}]
|
|
|
|
from_entries
|
|
[{"key":"a", "value":1}, {"Key":"b", "Value":2}, {"name":"c", "value":3}, {"Name":"d", "Value":4}]
|
|
{"a": 1, "b": 2, "c": 3, "d": 4}
|
|
|
|
with_entries(.key |= "KEY_" + .)
|
|
{"a": 1, "b": 2}
|
|
{"KEY_a": 1, "KEY_b": 2}
|
|
|
|
map(has("foo"))
|
|
[{"foo": 42}, {}]
|
|
[true, false]
|
|
|
|
map(has(2))
|
|
[[0,1], ["a","b","c"]]
|
|
[false, true]
|
|
|
|
keys
|
|
[42,3,35]
|
|
[0,1,2]
|
|
|
|
[][.]
|
|
1000000000000000000
|
|
null
|
|
|
|
map([1,2][0:.])
|
|
[-1, 1, 2, 3, 1000000000000000000]
|
|
[[1], [1], [1,2], [1,2], [1,2]]
|
|
|
|
# Test recursive object merge
|
|
|
|
{"k": {"a": 1, "b": 2}} * .
|
|
{"k": {"a": 0,"c": 3}}
|
|
{"k": {"a": 0, "b": 2, "c": 3}}
|
|
|
|
{"k": {"a": 1, "b": 2}, "hello": {"x": 1}} * .
|
|
{"k": {"a": 0,"c": 3}, "hello": 1}
|
|
{"k": {"a": 0, "b": 2, "c": 3}, "hello": 1}
|
|
|
|
{"k": {"a": 1, "b": 2}, "hello": 1} * .
|
|
{"k": {"a": 0,"c": 3}, "hello": {"x": 1}}
|
|
{"k": {"a": 0, "b": 2, "c": 3}, "hello": {"x": 1}}
|
|
|
|
{"a": {"b": 1}, "c": {"d": 2}, "e": 5} * .
|
|
{"a": {"b": 2}, "c": {"d": 3, "f": 9}}
|
|
{"a": {"b": 2}, "c": {"d": 3, "f": 9}, "e": 5}
|
|
|
|
[.[]|arrays]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[[],[3,[]]]
|
|
|
|
[.[]|objects]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[{}]
|
|
|
|
[.[]|iterables]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[[],[3,[]],{}]
|
|
|
|
[.[]|scalars]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[1,2,"foo",true,false,null]
|
|
|
|
[.[]|values]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[1,2,"foo",[],[3,[]],{},true,false]
|
|
|
|
[.[]|booleans]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[true,false]
|
|
|
|
[.[]|nulls]
|
|
[1,2,"foo",[],[3,[]],{},true,false,null]
|
|
[null]
|
|
|
|
flatten
|
|
[0, [1], [[2]], [[[3]]]]
|
|
[0, 1, 2, 3]
|
|
|
|
flatten(0)
|
|
[0, [1], [[2]], [[[3]]]]
|
|
[0, [1], [[2]], [[[3]]]]
|
|
|
|
flatten(2)
|
|
[0, [1], [[2]], [[[3]]]]
|
|
[0, 1, 2, [3]]
|
|
|
|
flatten(2)
|
|
[0, [1, [2]], [1, [[3], 2]]]
|
|
[0, 1, 2, 1, [3], 2]
|
|
|
|
try flatten(-1) catch .
|
|
[0, [1], [[2]], [[[3]]]]
|
|
"flatten depth must not be negative"
|
|
|
|
transpose
|
|
[[1], [2,3]]
|
|
[[1,2],[null,3]]
|
|
|
|
ascii_upcase
|
|
"useful but not for é"
|
|
"USEFUL BUT NOT FOR é"
|
|
|
|
bsearch(0,2,4)
|
|
[1,2,3]
|
|
-1
|
|
1
|
|
-4
|
|
|
|
# strptime tests are in optional.test
|
|
|
|
strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
[2015,2,5,23,51,47,4,63]
|
|
"2015-03-05T23:51:47Z"
|
|
|
|
strftime("%A, %B %d, %Y")
|
|
1435677542.822351
|
|
"Tuesday, June 30, 2015"
|
|
|
|
gmtime
|
|
1425599507
|
|
[2015,2,5,23,51,47,4,63]
|
|
|
|
# module system
|
|
import "a" as foo; import "b" as bar; def fooa: foo::a; [fooa, bar::a, bar::b, foo::a]
|
|
null
|
|
["a","b","c","a"]
|
|
|
|
import "c" as foo; [foo::a, foo::c]
|
|
null
|
|
[0,"acmehbah"]
|
|
|
|
include "c"; [a, c]
|
|
null
|
|
[0,"acmehbah"]
|
|
|
|
import "data" as $e; import "data" as $d; [$d[].this,$e[].that,$d::d[].this,$e::e[].that]|join(";")
|
|
null
|
|
"is a test;is too;is a test;is too"
|
|
|
|
include "shadow1"; e
|
|
null
|
|
2
|
|
|
|
include "shadow1"; include "shadow2"; e
|
|
null
|
|
3
|
|
|
|
import "shadow1" as f; import "shadow2" as f; import "shadow1" as e; [e::e, f::e]
|
|
null
|
|
[2,3]
|
|
|
|
%%FAIL
|
|
module (.+1); 0
|
|
jq: error: Module metadata must be constant at <top-level>, line 1:
|
|
|
|
%%FAIL
|
|
include "a" (.+1); 0
|
|
jq: error: Module metadata must be constant at <top-level>, line 1:
|
|
|
|
%%FAIL
|
|
include "a" []; 0
|
|
jq: error: Module metadata must be an object at <top-level>, line 1:
|
|
|
|
%%FAIL
|
|
include "\ "; 0
|
|
jq: error: Invalid escape at line 1, column 4 (while parsing '"\ "') at <top-level>, line 1:
|
|
|
|
%%FAIL
|
|
include "\(a)"; 0
|
|
jq: error: Import path must be constant at <top-level>, line 1:
|
|
|
|
modulemeta
|
|
"c"
|
|
{"whatever":null,"deps":[{"as":"foo","is_data":false,"relpath":"a"},{"search":"./","as":"d","is_data":false,"relpath":"d"},{"search":"./","as":"d2","is_data":false,"relpath":"d"},{"search":"./../lib/jq","as":"e","is_data":false,"relpath":"e"},{"search":"./../lib/jq","as":"f","is_data":false,"relpath":"f"},{"as":"d","is_data":true,"relpath":"data"}]}
|
|
|
|
modulemeta | .deps |= length
|
|
"c"
|
|
{"whatever":null,"deps":6}
|
|
|
|
%%FAIL IGNORE MSG
|
|
import "syntaxerror" as e; .
|
|
jq: error: syntax error, unexpected ';', expecting $end (Unix shell quoting issues?) at /home/nico/ws/jq/tests/modules/syntaxerror/syntaxerror.jq, line 1:
|
|
|
|
%%FAIL IGNORE MSG
|
|
%::wat
|
|
jq: error: syntax error, unexpected '%', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
|
|
|
|
import "test_bind_order" as check; check::check
|
|
null
|
|
true
|
|
|
|
try -. catch .
|
|
"very-long-string"
|
|
"string (\"very-long-...) cannot be negated"
|
|
|
|
join(",")
|
|
["1",2,true,false,3.4]
|
|
"1,2,true,false,3.4"
|
|
|
|
.[] | join(",")
|
|
[[], [null], [null,null], [null,null,null]]
|
|
""
|
|
""
|
|
","
|
|
",,"
|
|
|
|
.[] | join(",")
|
|
[["a",null], [null,"a"]]
|
|
"a,"
|
|
",a"
|
|
|
|
try join(",") catch .
|
|
["1","2",{"a":{"b":{"c":33}}}]
|
|
"string (\"1,2,\") and object ({\"a\":{\"b\":{...) cannot be added"
|
|
|
|
try join(",") catch .
|
|
["1","2",[3,4,5]]
|
|
"string (\"1,2,\") and array ([3,4,5]) cannot be added"
|
|
|
|
{if:0,and:1,or:2,then:3,else:4,elif:5,end:6,as:7,def:8,reduce:9,foreach:10,try:11,catch:12,label:13,import:14,include:15,module:16}
|
|
null
|
|
{"if":0,"and":1,"or":2,"then":3,"else":4,"elif":5,"end":6,"as":7,"def":8,"reduce":9,"foreach":10,"try":11,"catch":12,"label":13,"import":14,"include":15,"module":16}
|
|
|
|
try (1/.) catch .
|
|
0
|
|
"number (1) and number (0) cannot be divided because the divisor is zero"
|
|
|
|
try (1%.) catch .
|
|
0
|
|
"number (1) and number (0) cannot be divided (remainder) because the divisor is zero"
|
|
|
|
%%FAIL
|
|
1/0
|
|
jq: error: Division by zero? at <top-level>, line 1:
|
|
|
|
# Basic numbers tests: integers, powers of two
|
|
[range(-52;52;1)] as $powers | [$powers[]|pow(2;.)|log2] == $powers
|
|
null
|
|
true
|
|
|
|
[range(-99/2;99/2;1)] as $orig | [$orig[]|pow(2;.)|log2] as $back | ($orig|keys)[]|. as $k | (($orig|.[$k])-($back|.[$k]))|if . < 0 then . * -1 else . end|select(.>.00005)
|
|
null
|
|
|
|
%%FAIL IGNORE MSG
|
|
}
|
|
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
|
|
|
|
(.[{}] = 0)?
|
|
null
|
|
|
|
INDEX(range(5)|[., "foo\(.)"]; .[0])
|
|
null
|
|
{"0":[0,"foo0"],"1":[1,"foo1"],"2":[2,"foo2"],"3":[3,"foo3"],"4":[4,"foo4"]}
|
|
|
|
JOIN({"0":[0,"abc"],"1":[1,"bcd"],"2":[2,"def"],"3":[3,"efg"],"4":[4,"fgh"]}; .[0]|tostring)
|
|
[[5,"foo"],[3,"bar"],[1,"foobar"]]
|
|
[[[5,"foo"],null],[[3,"bar"],[3,"efg"]],[[1,"foobar"],[1,"bcd"]]]
|
|
|
|
range(5;10)|IN(range(10))
|
|
null
|
|
true
|
|
true
|
|
true
|
|
true
|
|
true
|
|
|
|
range(5;13)|IN(range(0;10;3))
|
|
null
|
|
false
|
|
true
|
|
false
|
|
false
|
|
true
|
|
false
|
|
false
|
|
false
|
|
|
|
range(10;12)|IN(range(10))
|
|
null
|
|
false
|
|
false
|
|
|
|
IN(range(10;20); range(10))
|
|
null
|
|
false
|
|
|
|
IN(range(5;20); range(10))
|
|
null
|
|
true
|
|
|
|
# Regression test for #1347
|
|
(.a as $x | .b) = "b"
|
|
{"a":null,"b":null}
|
|
{"a":null,"b":"b"}
|
|
|
|
# Regression test for #1368
|
|
(.. | select(type == "object" and has("b") and (.b | type) == "array")|.b) |= .[0]
|
|
{"a": {"b": [1, {"b": 3}]}}
|
|
{"a": {"b": 1}}
|
|
|
|
isempty(empty)
|
|
null
|
|
true
|
|
|
|
isempty(range(3))
|
|
null
|
|
false
|
|
|
|
isempty(1,error("foo"))
|
|
null
|
|
false
|
|
|
|
# Regression test for #1815
|
|
index("")
|
|
""
|
|
null
|
|
|
|
# check that dead code removal occurs after builtin it generation
|
|
builtins|length > 10
|
|
null
|
|
true
|
|
|
|
"-1"|IN(builtins[] / "/"|.[1])
|
|
null
|
|
false
|
|
|
|
all(builtins[] / "/"; .[1]|tonumber >= 0)
|
|
null
|
|
true
|
|
|
|
builtins|any(.[:1] == "_")
|
|
null
|
|
false
|
|
|
|
## Test ability to use keywords (uncomment after eval is pushed)
|
|
#(.[] as $kw | "\"{\($kw)} as $\($kw) | $\($kw) | {$\($kw)} | {\($kw):.\($kw)}\""|eval|empty),null
|
|
#["as","def","module","import","include","if","then","else","elif","end","reduce","foreach","and","or","try","catch","label","break","__loc__"]
|
|
#null
|
|
#
|
|
#(.[] as $kw | "\"def f($\($kw)): $\($kw); f(.)\""|eval|empty),null
|
|
#["as","def","module","import","include","if","then","else","elif","end","reduce","foreach","and","or","try","catch","label","break","__loc__"]
|
|
#null
|
|
|
|
|
|
#
|
|
# Tests to cover the new toliteral number functionality
|
|
# For an example see #1652 and other linked issues
|
|
#
|
|
|
|
# We are backward and sanity compatible
|
|
|
|
map(. == 1)
|
|
[1, 1.0, 1.000, 100e-2, 1e+0, 0.0001e4]
|
|
[true, true, true, true, true, true]
|
|
|
|
# When no arithmetic is involved jq should preserve the literal value
|
|
|
|
.[0] | tostring
|
|
[13911860366432393]
|
|
"13911860366432393"
|
|
|
|
.x | tojson
|
|
{"x":13911860366432393}
|
|
"13911860366432393"
|
|
|
|
13911860366432393 == 13911860366432392
|
|
null
|
|
false
|
|
|
|
|
|
# Applying arithmetic to the value will truncate the result to double
|
|
|
|
. - 10
|
|
13911860366432393
|
|
13911860366432382
|
|
|
|
.[0] - 10
|
|
[13911860366432393]
|
|
13911860366432382
|
|
|
|
.x - 10
|
|
{"x":13911860366432393}
|
|
13911860366432382
|