jq命令的基本介绍
# 常用命令-jq
jq (opens new window) 是个非常强大的处理 JSON 数据的命令行工具,本文主要讲的是常用的 <jq filter>
,大部分操作可以通过 jq play (opens new window) 直接在线测试。
# 一、基本操作
- jq 的命令行使用方法如下:
$ jq -h
# jq - commandline JSON processor [version 1.5]
# Usage: jq [options] <jq filter> [file...]
1
2
3
2
3
# 1 数据输出
# 1.1 输出原始的 JSON 数据
- 默认不指定 filter 就会原样输出,也可以使用
.
过滤器
echo '{"url": "[mozillazg.com](http://mozillazg.com/)"}' |jq .
# {
# "url": "[mozillazg.com](http://mozillazg.com/)"
# }
1
2
3
4
2
3
4
# 1.2 紧凑(compact)输出
echo '{
"b": "hello",
"d": "hello",
"a": "hello",
"c": "hello"
}' | jq --compact-output
# {"b":"hello","d":"hello","a":"hello","c":"hello"}
1
2
3
4
5
6
7
2
3
4
5
6
7
echo '{"k1":"v1","k2":"v2"}' | jq '[.k1, .k3 // ""]'
# [
# "v1",
# ""
# ]
echo '{"k1":"v1","k2":"v2"}' | jq -c '[.k1, .k3 // ""]'
# ["v1",""]
1
2
3
4
5
6
7
2
3
4
5
6
7
# 1.3 按照 Key 排序删除
echo '{
"b": "hello",
"d": "hello",
"a": "hello",
"c": "hello"
}' | jq --sort-keys
# {
# "a": "hello",
# "b": "hello",
# "c": "hello",
# "d": "hello"
# }
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 2 object 操作
# 2.1 获取某个 key 的值
- `.key, .foo.bar, .["key"]`
echo '{"url": "[mozillazg.com](http://mozillazg.com/)"}' |jq .url
# "[mozillazg.com](http://mozillazg.com/)"
echo '{"url": "[mozillazg.com](http://mozillazg.com/)"}' | jq '.["url"]'
# "[mozillazg.com](http://mozillazg.com/)"
1
2
3
4
5
6
2
3
4
5
6
- 可以在后面加个问号表示当输入不是 object 时不会报错
.key?
:
echo '1' |jq '.a'
# jq: error (at <stdin>:1): Cannot index number with string "a"
echo '1' |jq '.a?'
1
2
3
4
2
3
4
?
规则适合所有正确的 filter,在 filter 最后加上?
可以忽略错误信息
# 2.2 取某几个 key 的值
echo '{"foo": 42, "bar": "something else", "baz": true}' | jq '.foo, .bar'
# 42
# "something else"
echo '{"foo": 42, "bar": "something else", "baz": true}' | jq '[.foo, .bar]'
# [
# 42,
# "something else"
# ]
echo '{"foo": 42, "bar": "something else", "baz": true}' | jq -c '[.foo, .bar]'
# [42,"something else"]
echo '{"foo": 42, "bar": "something else", "baz": true}' | jq -c '{foo: .foo, bar:.bar}'
# {"foo":42,"bar":"something else"}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.3 所有的 key 组成的数组
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq keys
# [
# "name",
# "url"
# ]
1
2
3
4
5
2
3
4
5
# 2.4 所有的 value
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq .[]
# "[mozillazg.com](http://mozillazg.com/)"
# "mozillazg"
1
2
3
2
3
# 2.5 所有的 value 组成的数组
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq [.[]]
# [
# "[mozillazg.com](http://mozillazg.com/)",
# "mozillazg"
# ]
1
2
3
4
5
2
3
4
5
# 2.6 添加某个字段
# 新增:
echo '{"hello":"world"}' | jq '. +={"debug":1}'
# {
# "hello": "world",
# "debug": 1
# }
# 覆盖
echo '{"hello":"world", "debug":"a"}' | jq '. +={"debug":1}'
# {
# "hello": "world",
# "debug": 1
# }
# 引用变量
$ debug=100;echo '{"hello":"world", "debug":"a"}' | jq '. +={"debug":'"$debug"'}'
# {
# "hello": "world",
# "debug": 100
# }
$ debug=100;echo '{"hello":"world", "debug":"a"}' | jq '. +={"debug":"'"$debug"'"}'
# {
# "hello": "world",
# "debug": "100"
# }
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
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
# Add field
echo '{"hello": "world"}' | jq --arg foo bar '. + {foo: $foo}'
# {
# "hello": "world",
# "foo": "bar"
# }
# Override field value
echo '{"hello": "world"}' | jq --arg foo bar '. + {hello: $foo}'
# {
# "hello": "bar"
# }
# Concat and add
echo '{"hello": "world"}' | jq --arg foo bar '. + {hello: ("not" + $foo)}'
# {
# "hello": "world",
# "foo": "notbar"
# }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.7 删除某个字段
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' | jq 'del(.name)'
# {
# "url": "[mozillazg.com](http://mozillazg.com/)"
# }
1
2
3
4
2
3
4
# 2.8 某字段不存在则使用默认值
echo '{"k1":"v1","k2":"v2"}' | jq '.k1, .k3 // ""'
# "v1"
# ""
1
2
3
2
3
# 2.9 判断某字段是否存在
echo '{"k1":"v1","k2":"v2"}' | jq 'has("k1"),has("k3")'
# true
# false
echo '{"user":{"profile":{"age":20,"gender":"M"}}}' | jq '.user.profile | has("age")'
# true
echo '{"user":{"profile":{"age":20,"gender":"M"}}}' | jq '.user.profile | has("address")'
# false
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 2.10 jq to awk
echo '{"k1":"v1","k2":"v2"}' | jq '[.k1, .k2] | map(tostring) | join(",")'
# "v1,v2"
$ echo '{"k1":"v1","k2":"v2"}' | jq '[.k1, .k2] | map(tostring) | join(",")' | sed 's/"//g'
# v1,v2
echo '{"k1":"v1","k2":"v2"}' | jq '[.k1, .k2] | map(tostring) | join(" ")' | sed 's/"//g'
# v1 v2
1
2
3
4
5
6
2
3
4
5
6
# 2.11 删除某元素
echo '{"k1":"v1","k2":"v2"}' | jq 'del(.k1)'
# {"k2":"v2"}
echo '[{"name": "tom", "id":"1"}, {"name": "mozillazg","id":"2"}]' | jq -c 'del(.[].name)'
# [{"id":"1"},{"id":"2"}]
echo '[{"name": "tom", "id":"1"}, {"name": "mozillazg","id":"2"}]' | jq -c 'del(.[0].name)'
# [{"id":"1"},{"name":"mozillazg","id":"2"}]
1
2
3
4
5
6
2
3
4
5
6
# 3 数组操作
# 3.1 取出所有元素
echo '[{"name": "tom"}, {"name": "mozillazg"}]' |jq .[]
# {
# "name": "tom"
# }
# {
# "name": "mozillazg"
# }
1
2
3
4
5
6
7
2
3
4
5
6
7
# 3.2 取出所有元素的某个key
echo '[{"k1":1,"k2":2,"k3":3},{"k1":11,"k2":12,"k3":13},{"k1":21,"k2":22,"k3":23}]' | jq '.[]' | jq -c '{k1:.k1}'
# {"k1":1}
# {"k1":11}
# {"k1":21}
1
2
3
4
2
3
4
# 3.3 切分(slice)
.[1], .[0:2]
echo '[{"name": "tom"}, {"name": "mozillazg"}, {"name": "jim"}]' |jq .[1]
# {
# "name": "mozillazg"
# }
echo '[{"name": "tom"}, {"name": "mozillazg"}, {"name": "jim"}]' |jq .[1].name
# "mozillazg"
echo '[{"name": "tom"}, {"name": "mozillazg"}, {"name": "jim"}]' |jq .[0:2]
# [
# {
# "name": "tom"
# },
# {
# "name": "mozillazg"
# }
# ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.4 操作 object 组成的数组
echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq .[].name
# "foo"
# "bar"
# "foobar"
1
2
3
4
2
3
4
echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq '.[]|.name'
# "foo"
# "bar"
# "foobar"
1
2
3
4
2
3
4
- 如果要将结果重新组成数组,可以这样:
echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq [.[].name]
# [
# "foo",
# "bar",
# "foobar"
# ]
1
2
3
4
5
6
2
3
4
5
6
- 也可以使用下面会提到的 map:
echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq 'map(.name)'
[
"foo",
"bar",
"foobar"
]
1
2
3
4
5
6
2
3
4
5
6
# 3.5 获取数组的元素个数
echo '{"a":[1,2]}' | jq '.a|length'
# 2
1
2
2
# 4 字符串操作
# 4.1 获取字符串的元素个数
echo '{"a":"hello"}' | jq '.a|length'
# 5
1
2
2
# 4.2 使用多个 filter
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '.url, .name'
# "[mozillazg.com](http://mozillazg.com/)"
# "mozillazg"
1
2
3
2
3
# 二、高级操作
# 1 管道
- 可以通过 | 实现类似管道的功能:
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '.|.url'
# "[mozillazg.com](http://mozillazg.com/)"
1
2
2
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "tests": [{"foobar": "v1"}, {"foobar": "v2"}]}' |jq '.tests |.[] |.foobar'
# "v1"
# "v2"
1
2
3
2
3
- 也可以直接用 shell 的 | 实现:
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '.' | jq '.url'
# "[mozillazg.com](http://mozillazg.com/)"
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "tests": [{"foobar": "v1"}, {"foobar": "v2"}]}' |jq '.tests' | jq '.[]' | jq '.foobar'
# "v1"
# "v2"
1
2
3
4
5
6
2
3
4
5
6
# 2 获取内容的长度
- length 可以获取字符串或数组的长度:
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '.url|length'
# 13
echo '["[mozillazg.com](http://mozillazg.com/)", "mozillazg"]' |jq '.|length'
# 2
1
2
3
4
5
2
3
4
5
# 3 map
- map(foo) 可以实现对数组的每一项进行操作,然后合并结果的功能:
echo '["[mozillazg.com](http://mozillazg.com/)", "mozillazg"]' | jq 'map(length)'
# [
# 38,
# 9
# ]
echo '["[mozillazg.com](http://mozillazg.com/)", "mozillazg"]' | jq 'map(length)|add'
# 47
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 4 select
- select(foo) 可以实现对输入项进行判断,只返回符合条件的项:
echo '["[mozillazg.com](http://mozillazg.com/)", "mozillazg"]' | jq 'map(select(.|length > 9))'
# [
# "[mozillazg.com](http://mozillazg.com/)"
# ]
1
2
3
4
2
3
4
# 5 字符串插值,拼接
- 可以使用
\\(foo)
实现字符串插值功能:
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '"hi \\(.name)"'
# "hi mozillazg"
1
2
2
- 注意要用双引号包围起来,表示是一个字符串,使用 + 实现字符串拼接:
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '"hi " + .name'
# "hi mozillazg"
1
2
2
# 6 输出字符串原始值
- 使用
\-r
选项输出字符串原始值而不是 json 序列化后的值:
echo '{"value":"{\"url\":\"[mozillazg.com](http://mozillazg.com/)\"}"}' |jq .value
# "{\\"url\\": \\"[mozillazg.com](http://mozillazg.com/)\\"}"
echo '{"value":"{\"url\":\"[mozillazg.com](http://mozillazg.com/)\"}"}' |jq -r .value
# {"url": "[mozillazg.com](http://mozillazg.com/)"}
1
2
3
4
5
2
3
4
5
# 7 if/elif/else
- 可以使用
if .. then .. elif .. then .. else .. end
实现条件判断:
echo '[0, 1, 2, 3]' | jq 'map(if . == 0 then "zero" elif . == 1 then "one" elif . == 2 then "two" else "many" end)'
# [
# "zero",
# "one",
# "two",
# "many"
# ]
1
2
3
4
5
6
7
2
3
4
5
6
7
# 8 构造 object 或数组
- 可以通过 {} 和 [] 构造新的 object 或 数组。
echo '["[mozillazg.com](http://mozillazg.com/)", "mozillazg"]' |jq '{name: .[1]}'
# {
# "name": "mozillazg"
# }
1
2
3
4
2
3
4
echo '{"url": "[mozillazg.com](http://mozillazg.com/)", "name": "mozillazg"}' |jq '[.name, .url]'
# [
# "mozillazg",
# "[mozillazg.com](http://mozillazg.com/)"
# ]
1
2
3
4
5
2
3
4
5
echo '{"name": "mozillazg", "ages": [1, 2]}' | jq '{name, age: .ages[]}'
# {
# "name": "mozillazg",
# "age": 1
# }
# {
# "name": "mozillazg",
# "age": 2
# }
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 9 数组 join
echo '["[mozillazg.com](http://mozillazg.com/)", "mozillazg"]' | jq '.|join(" | ")'
# "[mozillazg.com](http://mozillazg.com/) | mozillazg"
1
2
2
# 10 字符串 split
echo '"[mozillazg.com](http://mozillazg.com/) | mozillazg"' |jq 'split(" | ")'
# [
# "[mozillazg.com](http://mozillazg.com/)",
# "mozillazg"
# ]
1
2
3
4
5
2
3
4
5
# 11 to_entries
{
"services": {
"10000021": {
"mobile": {
"business": "10000021",
"floor_price": {
"price": 1
}
}
},
"10000190": {
"mobile": {
"business": "10000190",
"floor_price": {
"price": 1
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 从上述json中提取 price
$ cat file | jq '.services | to_entries[].value|to_entries[].value' | jq -c '{business:.business, price:.floor_price.price}'
# {"business":"10000021","price":1}
# {"business":"10000190","price":1}
cat file | jq '.services|to_entries[]' | jq -c '{key:.key, price:.value|to_entries[].value.floor_price.price }'
# {"key":"10000021","price":1}
# {"key":"10000190","price":1}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 12 算数运算
echo '{"k":"k", "v":10}' | jq '{k:.k, v:(.v*10)}'
# {
# "k": "k",
# "v": 100
# }
1
2
3
4
5
2
3
4
5
# 13 jq 引用 shell 变量
$ export k="v"
echo '{"a":1}' | jq --arg k $k -c '{a:.a,k:$k}'
# {"a":1,"k":"v"}
1
2
3
2
3
# 参考资料
- jq: https://stedolan.github.io/jq/
- jq play: https://jqplay.org/ *【jq 中文手册(v1.5) _ jq 中文手册】 http://alingse.github.io/jq-manual-cn/manual/v1.5/
- JSON解析工具-jq: https://hellogitlab.com/OS/Centos/json_tool_jq.html
编辑 (opens new window)
上次更新: 2024/10/23, 19:38:27