-
-
Notifications
You must be signed in to change notification settings - Fork 120
/
builtin.jq
187 lines (176 loc) · 5 KB
/
builtin.jq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
def not: if . then false else true end;
def in(xs): . as $x | xs | has($x);
def map(f): [.[] | f];
def with_entries(f): to_entries | map(f) | from_entries;
def select(f): if f then . else empty end;
def recurse: recurse(.[]?);
def recurse(f): def r: ., (f | r); r;
def recurse(f; cond): def r: ., (f | select(cond) | r); r;
def while(cond; update):
def _while: if cond then ., (update | _while) else empty end;
_while;
def until(cond; next):
def _until: if cond then . else next | _until end;
_until;
def repeat(f):
def _repeat: f, _repeat;
_repeat;
def range($end): _range(0; $end; 1);
def range($start; $end): _range($start; $end; 1);
def range($start; $end; $step): _range($start; $end; $step);
def add(f): [f] | add;
def min_by(f): _min_by(map([f]));
def max_by(f): _max_by(map([f]));
def sort_by(f): _sort_by(map([f]));
def group_by(f): _group_by(map([f]));
def unique_by(f): _unique_by(map([f]));
def arrays: select(type == "array");
def objects: select(type == "object");
def iterables: select(type | . == "array" or . == "object");
def booleans: select(type == "boolean");
def numbers: select(type == "number");
def finites: select(isfinite);
def normals: select(isnormal);
def strings: select(type == "string");
def nulls: select(. == null);
def values: select(. != null);
def scalars: select(type | . != "array" and . != "object");
def inside(xs): . as $x | xs | contains($x);
def combinations:
if length == 0 then
[]
else
.[0][] as $x | [$x] + (.[1:] | combinations)
end;
def combinations(n): [limit(n; repeat(.))] | combinations;
def walk(f):
def _walk:
if type == "array" then
map(_walk)
elif type == "object" then
map_values(_walk)
end | f;
_walk;
def first: .[0];
def first(g): label $out | g | ., break $out;
def last: .[-1];
def isempty(g): label $out | (g | false, break $out), true;
def all: all(.);
def all(y): all(.[]; y);
def all(g; y): isempty(g | select(y | not));
def any: any(.);
def any(y): any(.[]; y);
def any(g; y): isempty(g | select(y)) | not;
def limit($n; g):
if $n > 0 then
label $out |
foreach g as $item (
$n;
. - 1;
$item, if . <= 0 then break $out else empty end
)
elif $n == 0 then
empty
else
error("limit doesn't support negative count")
end;
def skip($n; g):
if $n > 0 then
foreach g as $item (
$n;
. - 1;
if . < 0 then $item else empty end
)
elif $n == 0 then
g
else
error("skip doesn't support negative count")
end;
def nth($n): .[$n];
def nth($n; g):
if $n >= 0 then
first(skip($n; g))
else
error("nth doesn't support negative index")
end;
def truncate_stream(f):
. as $n | null | f |
if .[0] | length > $n then .[0] |= .[$n:] else empty end;
def fromstream(f):
foreach f as $pv (
null;
if .e then null end |
$pv as [$p, $v] |
if $pv | length == 2 then
setpath(["v"] + $p; $v) |
setpath(["e"]; $p | length == 0)
else
setpath(["e"]; $p | length == 1)
end;
if .e then .v else empty end
);
def tostream:
path(def r: (.[]? | r), .; r) as $p |
getpath($p) |
reduce path(.[]?) as $q ([$p, .]; [$p + $q]);
def map_values(f): .[] |= f;
def del(f): delpaths([path(f)]);
def paths: path(..) | select(. != []);
def paths(f): path(.. | select(f)) | select(. != []);
def pick(f): . as $v |
reduce path(f) as $p (null; setpath($p; $v | getpath($p)));
def fromdateiso8601: strptime("%Y-%m-%dT%H:%M:%S%z") | mktime;
def todateiso8601: strftime("%Y-%m-%dT%H:%M:%SZ");
def fromdate: fromdateiso8601;
def todate: todateiso8601;
def match($re): match($re; null);
def match($re; $flags): _match($re; $flags; false)[];
def test($re): test($re; null);
def test($re; $flags): _match($re; $flags; true);
def capture($re): capture($re; null);
def capture($re; $flags): match($re; $flags) | _capture;
def scan($re): scan($re; null);
def scan($re; $flags):
match($re; $flags + "g") |
if .captures == [] then
.string
else
[.captures[].string]
end;
def splits($re): splits($re; null);
def splits($re; $flags): split($re; $flags)[];
def sub($re; str): sub($re; str; null);
def sub($re; str; $flags):
. as $str |
def _sub:
if .matches == [] then
$str[:.offset] + .string
else
.matches[-1] as $r |
{
string: ($r | _capture | str) + $str[$r.offset+$r.length:.offset] + .string,
offset: $r.offset,
matches: .matches[:-1],
} |
_sub
end;
{ string: "", matches: [match($re; $flags)] } | _sub;
def gsub($re; str): sub($re; str; "g");
def gsub($re; str; $flags): sub($re; str; $flags + "g");
def inputs:
try
repeat(input)
catch
if . == "break" then empty else error end;
def INDEX(stream; idx_expr):
reduce stream as $row ({}; .[$row | idx_expr | tostring] = $row);
def INDEX(idx_expr):
INDEX(.[]; idx_expr);
def JOIN($idx; idx_expr):
[.[] | [., $idx[idx_expr]]];
def JOIN($idx; stream; idx_expr):
stream | [., $idx[idx_expr]];
def JOIN($idx; stream; idx_expr; join_expr):
stream | [., $idx[idx_expr]] | join_expr;
def IN(s): any(s == .; .);
def IN(src; s): any(src == s; .);