总结
cat [File] | jq '.[]':JSON转化JSONLcat [File] | jq -s '.':JSONL转化JSONcat [File] | jq '.key':JSONL路径取值,只输出特定的字段cat [File] | jq '{key}':JSONL抽取属性构建新对象,筛选特定字段进行输出cat [File] | jq 'select(.age > 24)':JSONL过滤cat [File] | jq '{age} | map_values(.+10)':JSONL映射cat [File] | jq 'sort_by(-.age)':JSON排序cat [File] | jq --stream:stream流式读取JSON- 与
less/tail结合使用less [File] | jq '.'tail -f [File] | jq '.'
提问
- [x] 1. 如何把 JSON 转化为 JSONL
cat [File] | jq '.[]' - [x] 2. 如何把 JSONL 转化为 JSON
cat [File] | jq -s '.' - [x] 3. 如何使 JSONL 只输出特定的字段
cat [File] | jq '.key' - [x] 4. 如何筛选 JSONL 特定字段进行输出
cat [File] | jq '{key}' - [x] 5. 如何与 less/tail 结合使用
less [File] | jq '.'tail -f [File] | jq '.'
1. 前提提要、场景
前端经常要和 JSON 打交道,各种配置文件也都是 JSON 格式。这便需要有个工具,可以操作 JSON —— jq
学习前请打开 jq 官方文档,内有完整示例。会频繁用到。
2. 安装
下载
curl -O https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64更改权限
chmod a+x jq-linux64移动到
bin目录mv jq-linux64 /usr/bin/jq
3. 示例准备
demo.jsonl: 模拟日志文件中,每行日志记录都是 json
JSONL即JSON Lines
$ cat <<EOF > demo.jsonl
{"name": "shanyue", "age": 24, "friend": {"name": "shuifeng"}}
{"name": "shuifeng", "age": 25, "friend": {"name": "shanyue"}}
EOF
demo.json: 模拟后台接口返回的数据
$ cat <<EOF > demo.json
[
{"name": "shanyue", "age": 24, "friend": {"name": "shuifeng"}},
{"name": "shuifeng", "age": 25, "friend": {"name": "shanyue"}}
]
EOF
4. jq 命令详解
命令:jq [options...] filter [files]
options: 选项filter: 转换操作,类似lodash函数
4.1 option 选项
常用选项:
-s:JSONL转JSON。将输入转换成个大数组 (如后续的 filter:group,sort只能以数组作为输入)-c: 不对做JSON格式化,一行输出。--stream: 对JSON逐字段输出
4.2 filter 转换操作
常用选项:
- 实现了 loadsh 的
get,map,filter,map,pick,uniq,group等 .: 代表自身.[]: 返回数组或对象里的所有值,且是以单独的结果返回,即JSONL.a.b: 取属性,相当于_.get(input, 'a.b')select(bool): 过滤,相当于_.filter(boolFn)map_values: 映射,相当于_.map,不过jq无法单独操作keysort: 排序group_by: 按字段分组
5. 场景示例
5.1 JSON to JSONL
# .[]: 返回数组或对象里的所有值,且是以单独的结果返回,即 JSONL
$ cat demo.json | jq '.[]'
{
"name": "shanyue",
"age": 24,
"friend": {
"name": "shuifeng"
}
}
{
"name": "shuifeng",
"age": 25,
"friend": {
"name": "shanyue"
}
}
5.2 JSONL to JSON
# -s: 代表把 jsonl 组成数组处理
$ cat demo.jsonl | jq -s '.'
[
{
"name": "shanyue",
"age": 24,
"friend": {
"name": "shuifeng"
}
},
{
"name": "shuifeng",
"age": 25,
"friend": {
"name": "shanyue"
}
}
]
5.3 . 路径取值
.: Object Identifier-Index: .foo, .foo.bar 类似 loadsh 的 _.get
$ cat demo.jsonl | jq '.name'
"shanyue"
"shuifeng"
5.4 {} 抽取属性构建新对象
{}: Object Construction: {} 类似 loadsh 的 _.pick
接收 JSONL
$ cat demo.jsonl | jq '{name, friendname: .friend.name}'
{
"name": "shanyue",
"friendname": "shuifeng"
}
{
"name": "shuifeng",
"friendname": "shanyue"
}
5.5 select 过滤
select: select(boolean_expression) 类似 loadsh 的 _.filter
# 先过滤,后抽取属性构建新对象
$ cat demo.jsonl | jq 'select(.age > 24) | {name}'
{
"name": "shuifeng"
}
5.6 map_values 映射
map_values: map(x), map_values(x) 类似 loadsh 的 _.map
# 先抽取属性构建新对象,后映射 + 10
$ cat demo.jsonl | jq '{age} | map_values(.+10)'
{
"age": 34
}
{
"age": 35
}
5.7 sort_by 排序
sort_by: sort, sort_by(path_expression) 类似 loadsh 的 _.sortBy
sort_by 只接受数组,所以要把 JSONL 转 JSON
# 按照 age 降序排列
# -s: jsonl to json
# -.age: 降序
# .[]: json to jsonl
# {}: pick
$ cat demo.jsonl | jq -s '. | sort_by(-.age) | .[] | {name, age}'
{
"name": "shuifeng",
"age": 25
}
{
"name": "shanyue",
"age": 24
}
# 按照 age 升序排列
$ cat demo.jsonl | jq -s '. | sort_by(.age) | .[] | {name, age}'
{
"name": "shanyue",
"age": 24
}
{
"name": "shuifeng",
"age": 25
}
5.8 stream 流
stream: Streaming
当字段嵌套过多时,逐字段查看 JSON 数据
$ cat demo.json
[
{"name": "shanyue", "age": 24, "friend": {"name": "shuifeng"}},
{"name": "shuifeng", "age": 25, "friend": {"name": "shanyue"}}
]
$ cat demo.json | jq --stream -c
[[0,"name"],"shanyue"]
[[0,"age"],24]
[[0,"friend","name"],"shuifeng"]
[[0,"friend","name"]]
[[0,"friend"]]
[[1,"name"],"shuifeng"]
[[1,"age"],25]
[[1,"friend","name"],"shanyue"]
[[1,"friend","name"]]
[[1,"friend"]]
[[1]]
5.9 jq with less (less 上的 jq 应用)
如果 JSON 数据过大时,可选择使用 less 查看数据,如果在 less 中需要语法高亮时,可使用 jq -C。
# -C: --color-output
$ cat demo.json | jq -C '.' | less
5.10 jq with log (tail 上的 jq 应用)
生产环境的日志往往通过 JSONL 格式进行文件存储,通常通过 tail -f 实时查看日志
如果只关注某几个重要指标,也可以进行筛选。
# 实时查看日志
$ tail -f demo.jsonl | jq '.'
# 如果只关注某个参数的话,也可以进行筛选
$ tail -f demo.jsonl | jq '{name}'
如果需要测试上面命令,可新开一个 shell,输入以下命令进行测试
# -c: 紧凑输出。 JSONL 只压缩第一行, JSON 所有都压缩成一行
$ cat demo.jsonl | jq -c '.' >> demo.jsonl