是jq的替代品,同样用于处理多行的json,可以通过预置的特性完成丰富的数据操作。
性能高,且能够内嵌到golang语言中。
operator是不带括号的,function是带括号的调用。比如cut a,以及flattern(a)。
操作符 | 功能说明 | 示例 | 备注 |
assert | 断言,成功或者返回错误 |
> echo {a:1} | zq -z 'assert a > 0' -
{a:1}
> echo {a:-1} | zq -z 'assert a > 0' -
error({message:"assertion failed",expr:"a > 0",on:{a:-1}}) |
跟where不同的就是是否报错 |
combine | 合并不同的来源到一份数据 |
echo '1 2' | zq -z 'fork (=>pass =>pass) ' -
1
2
1
2 |
fork是什么?pass是什么?参看fork 如何构造不同的数据来源?大约是from,后续需要确认。 |
cut | 只保留选定的几个字段 |
echo '{a:1,b:2,c:3}' | zq -z 'cut a,c' -
{a:1,c:3} |
|
drop | 删除特定的字段 |
echo '1 {a:1,b:2,c:3}' | zq -z 'drop a,b' -
1 {c:3} |
|
over | 展开为一维数组,然后进行遍历;可以带上with操作,根据key进行运算。 |
echo '{a:[6,5,4]} {a:[3,2,1]}' | zq -j 'over a' -
6
5
4
3
2
1
echo '{a:[1,2],s:"foo"} {a:[3,4,5],s:"bar"}' | zq -z 'over a with s => (sum(this) | yield {s,sum})' -
{s:"foo",sum:3}
{s:"bar",sum:12} |
over后带有括号就表名在处理一行 |
echo '{"port":81}' | zq -j 'cast(port,<string>)' -
"81"
echo '{"port":81}' | zq -j 'put port:=cast(port,<string>)' -
{"port":"81"}
echo '{"ip":"1.1.1.1","port":81}' | zq -j 'put c:="socks5://"+ip+":"+cast(port,<string>)' -
{"ip":"1.1.1.1","port":81,"c":"socks5://1.1.1.1:81"}
echo '{"port":81}' | zq -j "put port:='a'" -
{"port":"a"}
echo '{"port":81}' | zq -j 'put port:="a"' -
{"port":"a"}
echo '{"msg":"{\"code\":200}"}' | zq -j 'msg:=parse_zson(msg)' -
{"msg":{"code":200}}
❯ echo '{"a":null}\n{"a":[1,2]}' | zq -j 'a' -
{"a":null}
{"a":[1,2]}
❯ echo '{"a":null}\n{"a":[1,2]}' | zq -j 'len(a)>0' -
{"a":[1,2]}
echo '{"b":1, "a":[" 1 ", "2 ", " 3"]}' | zq -j 'over a with b => (trim(this) | collect(this) | yield {b,collect}) | rename host:=collect' -
{"b":1,"host":["1","2","3"]}
echo '{a:1}{b:2}{a:3}' | zq -j 'not a' -
{"b":2}
echo '{"a":"b","c":"d"}' | zq -j 'a:=replace(a, "b", "1")' -
{"a":"1","c":"d"}
echo '{"Sheet1":[["IP","域名"],["1.1.1.1","a.com"]],"Sheet2":[null,["Hello world."]]}' | zq -j 'over Sheet1 | this[0]' -
"IP"
"1.1.1.1"
echo '{"Sheet1":[["IP","域名"],["1.1.1.1","a.com"],["2.2.2.2","b.com"]],"Sheet2":[null,["Hello world."]]}' | zq -j 'yield {...this, ip:collect(over Sheet1 | flatten(this[0]))[0][1:]}' -
{"Sheet1":[["IP","域名"],["1.1.1.1","a.com"],["2.2.2.2","b.com"]],"Sheet2":[null,["Hello world."]],"ip":["1.1.1.1","2.2.2.2"]}
echo "[1,2,3]" | zq -j 'this[1:]' -
[2,3]
❯ echo '{"a":1,"b":2}' | jq keys -c
["a","b"]
❯ echo '{"a":1,"b":2}' | zq -j 'fields(this)' -
[["a"],["b"]]
zq -j 'fields(this) | over this | this[0] | collect(this) | yield collect' -
["a","b"]
echo '{".a":"1","b":2,"c":3}' | zq -j 'over this | key[0][0:1] != "."' -
{"key":["b"],"value":2}
{"key":["c"],"value":3}
echo '{".a":"1","b":2,"c":3}' | zq -j 'over this | key[0][0:1] != "." | collect(this)' -
{"collect":[{"key":["b"],"value":2},{"key":["c"],"value":3}]}
echo '{".a":"1","b":2,"c":3}' | zq -j 'over this | key[0][0:1] != "." | collect(this) | yield collect' -
[{"key":["b"],"value":2},{"key":["c"],"value":3}]
echo '{".a":"1","b":2,"c":3}' | zq -j 'over this | key[0][0:1] != "." | collect(this) | yield collect | yield unflatten(this)' -
{"b":2,"c":3}
上面这种方式只能处理一行,如何处理多行:
echo '{".a":"1","b":2,"c":3}\n{".a":"4","b":5,"c":6}' | zq -j 'over this =>(key[0][0:1] != "." | collect(this) | yield collect | over this => ( collect(this) | yield collect | yield unflatten(this) ) )' -
{"b":2,"c":3}
{"b":5,"c":6}
这个语句必须要在1.2.0版本才ok,否则提示
{"b":2,"c":3}
{"error":"unflatten: duplicate field: \"b\""}
echo '{"a.cvs":[["ip","domain"],["1.1.1.1","a.com"]]}\n{"b.cvs":[["ip","domain"],["2.2.2.2","b.com"]]}' | zq -j 'over this | value[1:][0][0] | collect(this)' -
{"collect":["1.1.1.1","2.2.2.2"]}
❯ echo '{"ip":"1.1.1.1","a":1}\n{"ip":"1.1.1.1","b":2}' | zq -j 'union(this) by ip | over union with ip1=ip => ( drop ip | union(this) | yield {ip:ip1,...this} ) ' -
{"ip":"1.1.1.1","union":[{"a":1},{"b":2}]}
如下这个不满足预期,预期返回:{"a":1}
❯ echo '{"name":"a","value":1}' | zq -j '{name:value}' -
{"name":1}
好像不行,要用jq
❯ echo '{"ip":"1.1.1.1","a":1}\n{"ip":"1.1.1.1","b":2}' | zq -j 'union(this) by ip | yield {...union[0], ...union[1]}' -
{"ip":"1.1.1.1","a":1,"b":2}
echo -n '{"a":"1","b":"2","c":"3"}\n{"a":"4","b":"5","c":"6"}' | zq -f csv -
a,b,c
1,2,3
4,5,6
暂时无解
echo '{"a":1,"b":1}' | zq -j 'cut a,b' -
{"a":1,"b":1}
echo '{"测试":1,"哈哈":1}' | zq -j 'cut 测试' -
zq: error parsing Zed at column 5:
cut 测试
=== ^ ===
echo '{"测试":1,"哈哈":1}' | zq -j 'cut "测试"' -
illegal left-hand side of assignment'
echo '{"测试":1,"哈哈":1}' | zq -j 'cut "测试","哈哈"' -
illegal left-hand side of assignment'
echo '{"ts":1671267600000000000}' | zq -j 'yield time(this.ts)' -
"2022-12-17T09:00:00Z"
echo '{"ts":"2022-12-17 09:00:00"}' | zq -j 'yield int64(time(this.ts))' -
1671267600000000000
# 取最大值
echo -n '{"ts":"2022-12-17 09:00:00"}\n{"ts":"2022-12-18 09:00:00"}' | zq -j 'yield time(this.ts) | max(this)' -
{"max":"2022-12-18T09:00:00Z"}
# 取最小值
echo -n '{"ts":"2022-12-17 09:00:00"}\n{"ts":"2022-12-18 09:00:00"}' | zq -j 'yield time(this.ts) | min(this)' -
{"min":"2022-12-17T09:00:00Z"}
# 日期的格式化输出在zq中暂时不支持,可以手动进行修改:
echo -n '{"ts":"2022-12-17 09:00:00"}\n{"ts":"2022-12-18 09:00:00"}' | zq -j 'yield time(this.ts) | min(this) | yield string(this.min) | yield replace(this, "Z", "") | yield replace(this, "T", " ")' -
"2022-12-17 09:00:00"
❯ echo '{"id":1,"a":[1,2]}' | zq -j 'over a with id=> (yield {id, a:this})' -
{"id":1,"a":1}
{"id":1,"a":2}
如果不带yield,那么取的是完整的结构,带了yield就会以新的表达式来返回,比如:
❯ echo '{"a":[" 1 ", "2 ", " 3"]}' | zq -j 'a' -
{"a":[" 1 ","2 "," 3"]}
❯ echo '{"a":[" 1 ", "2 ", " 3"]}' | zq -j 'yield a' -
[" 1 ","2 "," 3"]
union默认做了uniq操作,collect没有。
❯ echo '{"a":1}\n{"a":2}\n{"a":1,"b":2}\n{"a":1}' | zq -j 'c:=collect(this) by a' -
{"a":1,"c":[{"a":1},{"a":1,"b":2},{"a":1}]}
{"a":2,"c":[{"a":2}]}
❯ echo '{"a":1}\n{"a":2}\n{"a":1,"b":2}\n{"a":1}' | zq -j 'c:=union(this) by a' -
{"a":1,"c":[{"a":1},{"a":1,"b":2}]}
{"a":2,"c":[{"a":2}]}