| # 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|.,@base64d) |
| "!()<>&'\"\t" |
| "!()<>&'\"\t" |
| "\"!()<>&'\\\"\\t\"" |
| "1,\"!()<>&'\"\"\t\"" |
| "1\t!()<>&'\"\\t" |
| "!()<>&'"\t" |
| "%21%28%29%3C%3E%26%27%22%09" |
| "'!()<>&'\\''\"\t'" |
| "ISgpPD4mJyIJ" |
| "!()<>&'\"\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 |
| |
| .e0, .E1, .E-1, .E+1 |
| {"e0": 1, "E1": 2, "E": 3} |
| 1 |
| 2 |
| 2 |
| 4 |
| |
| [.[]|.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]] |
| |
| # chaining/suffix-list, with and without dot |
| map(try .a[] catch ., try .a.[] catch ., .a[]?, .a.[]?) |
| [{"a": [1,2]}, {"a": 123}] |
| [1,2,1,2,1,2,1,2,"Cannot iterate over number (123)","Cannot iterate over number (123)"] |
| |
| # |
| # 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(.))] |
| 10 |
| [0,9] |
| |
| [nth(0,5,9,10,15; range(.)), try nth(-1; range(.)) catch .] |
| 10 |
| [0,5,9,"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 evaluate 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] |
| |
| 1e-19 + 1e-20 - 5e-21 |
| null |
| 1.05e-19 |
| |
| 1 / 1e-17 |
| null |
| 1e+17 |
| |
| 5E500000000>5E-5000000000 |
| null |
| true |
| |
| 25 % 7 |
| null |
| 4 |
| |
| 49732 % 472 |
| null |
| 172 |
| |
| [(infinite, -infinite) % (1, -1, infinite)] |
| null |
| [0,0,0,0,0,-1] |
| |
| [nan % 1, 1 % nan | isnan] |
| null |
| [true,true] |
| |
| 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"]] |
| |
| ["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] |
| |
| # negative index |
| setpath([-1]; 1) |
| [0] |
| [1] |
| |
| pick(.a.b.c) |
| null |
| {"a":{"b":{"c":null}}} |
| |
| pick(first) |
| [1,2] |
| [1] |
| |
| pick(first|first) |
| [[10,20],30] |
| [[10]] |
| |
| # negative indices in path expressions (since last/1 is .[-1]) |
| pick(last) |
| [[10,20],30] |
| [null,30] |
| |
| # |
| # 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}]} |
| |
| # #2051, deletion using assigning empty against arrays |
| (.[] | select(. >= 2)) |= empty |
| [1,5,3,0,7] |
| [1,0] |
| |
| .[] |= select(. % 2 == 0) |
| [0,1,2,3,4,5] |
| [0,2,4] |
| |
| .foo[1,4,2,3] |= empty |
| {"foo":[0,1,2,3,4,5]} |
| {"foo":[0,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] |
| |
| [if false then 3 elif false then 4 end] |
| 7 |
| [7] |
| |
| [if false then 3 elif false then 4 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}] |
| [] |
| |
| [1,error,2] |
| null |
| [1,2] |
| |
| [1,error(null),2] |
| 0 |
| [1,2] |
| |
| 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]] |
| |
| [ index("aba"), rindex("aba"), indices("aba") ] |
| "xababababax" |
| [1,7,[1,3,5,7]] |
| |
| 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"] |
| |
| [.[] * "abc"] |
| [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 3.7, 10.0] |
| [null,null,"","","abc","abc","abcabcabc","abcabcabcabcabcabcabcabcabcabc"] |
| |
| [. * (nan,-nan)] |
| "abc" |
| [null,null] |
| |
| [.[] / ","] |
| ["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] |
| |
| has(nan) |
| [0,1,2] |
| false |
| |
| 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]] |
| |
| transpose |
| [] |
| [] |
| |
| 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] |
| |
| # test invalid tm input |
| try strftime("%Y-%m-%dT%H:%M:%SZ") catch . |
| ["a",1,2,3,4,5,6,7] |
| "strftime/1 requires parsed datetime inputs" |
| |
| try strflocaltime("%Y-%m-%dT%H:%M:%SZ") catch . |
| ["a",1,2,3,4,5,6,7] |
| "strflocaltime/1 requires parsed datetime inputs" |
| |
| try mktime catch . |
| ["a",1,2,3,4,5,6,7] |
| "mktime requires parsed datetime inputs" |
| |
| # 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" |
| |
| # Regression test for #2000 |
| import "data" as $a; import "data" as $b; def f: {$a, $b}; f |
| null |
| {"a":[{"this":"is a test","that":"is too"}],"b":[{"this":"is a test","that":"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 |
| module []; 0 |
| jq: error: Module metadata must be an object 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/0) catch . |
| 0 |
| "number (1) and number (0) cannot be divided because the divisor is zero" |
| |
| try (0/0) catch . |
| 0 |
| "number (0) 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" |
| |
| try (1%0) catch . |
| 0 |
| "number (1) and number (0) cannot be divided (remainder) because the divisor is zero" |
| |
| # Basic numbers tests: integers, powers of two |
| [range(-52;52;1)] as $powers | [$powers[]|pow(2;.)|log2|round] == $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 |
| |
| . |= try . catch . |
| 1 |
| 1 |
| |
| # abs, fabs, length |
| abs |
| "abc" |
| "abc" |
| |
| map(abs) |
| [-0, 0, -10, -1.1] |
| [0,0,10,1.1] |
| |
| map(fabs == length) | unique |
| [-10, -1.1, -1e-1, 1000000000000000002] |
| [true] |
| |
| # The following is NOT prescriptive: |
| map(abs) |
| [0.1,1000000000000000002] |
| [1e-1, 1000000000000000002] |
| |
| # Using a keyword as variable/label name |
| |
| 123 as $label | $label |
| null |
| 123 |
| |
| [ label $if | range(10) | ., (select(. == 5) | break $if) ] |
| null |
| [0,1,2,3,4,5] |
| |
| reduce .[] as $then (4 as $else | $else; . as $elif | . + $then * $elif) |
| [1,2,3] |
| 96 |
| |
| 1 as $foreach | 2 as $and | 3 as $or | { $foreach, $and, $or, a } |
| {"a":4,"b":5} |
| {"foreach":1,"and":2,"or":3,"a":4} |
| |
| [ foreach .[] as $try (1 as $catch | $catch - 1; . + $try; .) ] |
| [10,9,8,7] |
| [10,19,27,34] |
| |
| |
| # Object construction |
| |
| { a, $__loc__, c } |
| {"a":[1,2,3],"b":"foo","c":{"hi":"hey"}} |
| {"a":[1,2,3],"__loc__":{"file":"<top-level>","line":1},"c":{"hi":"hey"}} |
| |
| 1 as $x | "2" as $y | "3" as $z | { $x, as, $y: 4, ($z): 5, if: 6, foo: 7 } |
| {"as":8} |
| {"x":1,"as":8,"2":4,"3":5,"if":6,"foo":7} |
| |
| |
| # nan is parsed as a valid NaN value from JSON |
| |
| fromjson | isnan |
| "nan" |
| true |
| |
| tojson | fromjson |
| {"a":nan} |
| {"a":null} |
| |
| |
| # calling input/0, or debug/0 in a test doesn't crash jq |
| |
| try input catch . |
| null |
| "break" |
| |
| debug |
| 1 |
| 1 |
| |
| # try/catch catches more than it should #1859 |
| "foo" | try ((try . catch "caught too much") | error) catch "caught just right" |
| null |
| "caught just right" |
| |
| .[]|(try (if .=="hi" then . else error end) catch empty) | "\(.) there!" |
| ["hi","ho"] |
| "hi there!" |
| |
| try (["hi","ho"]|.[]|(try . catch (if .=="ho" then "BROKEN"|error else empty end)) | if .=="ho" then error else "\(.) there!" end) catch "caught outside \(.)" |
| null |
| "hi there!" |
| "caught outside ho" |
| |
| .[]|(try . catch (if .=="ho" then "BROKEN"|error else empty end)) | if .=="ho" then error else "\(.) there!" end |
| ["hi","ho"] |
| "hi there!" |
| |
| try (try error catch "inner catch \(.)") catch "outer catch \(.)" |
| "foo" |
| "inner catch foo" |
| |
| try ((try error catch "inner catch \(.)")|error) catch "outer catch \(.)" |
| "foo" |
| "outer catch inner catch foo" |
| |
| # Also #1859, but from #1885 |
| first(.?,.?) |
| null |
| null |
| |
| # Also #1859, but from #2140 |
| {foo: "bar"} | .foo |= .? |
| null |
| {"foo": "bar"} |
| |
| # Also #1859, but from #2220 |
| . |= try 2 |
| 1 |
| 2 |
| |
| . |= try 2 catch 3 |
| 1 |
| 2 |
| |
| .[] |= try tonumber |
| ["1", "2a", "3", 4] |
| [1, 3, 4] |
| |
| # Also 1859, but from 2073 |
| any(keys[]|tostring?;true) |
| {"a":"1","b":"2","c":"3"} |
| true |
| |
| |
| # explode/implode |
| # test replacement character (65533) for outside codepoint range and 0xd800 (55296) - 0xdfff (57343) utf16 surrogate pair range |
| # 1.1 and 1.9 to test round down of non-ints |
| implode|explode |
| [-1,0,1,2,3,1114111,1114112,55295,55296,57343,57344,1.1,1.9] |
| [65533,0,1,2,3,1114111,65533,55295,65533,65533,57344,1,1] |
| |
| map(try implode catch .) |
| [123,["a"],[nan]] |
| ["implode input must be an array","string (\"a\") can't be imploded, unicode codepoint needs to be numeric","number (null) can't be imploded, unicode codepoint needs to be numeric"] |
| |
| # walk |
| walk(.) |
| {"x":0} |
| {"x":0} |
| |
| walk(1) |
| {"x":0} |
| 1 |
| |
| # The following is a regression test, not a requirement: |
| [walk(.,1)] |
| {"x":0} |
| [{"x":0},1] |
| |
| # Issue #2584 |
| walk(select(IN({}, []) | not)) |
| {"a":1,"b":[]} |
| {"a":1} |