用 jq 解析 JSON:从取值到批量提取
接口返回的 JSON 一大段,直接用眼睛找字段又慢又容易漏。jq 就是专门处理 JSON 的命令行工具:它读入 JSON、按你写的表达式取值、过滤和重组,输出仍然是干净的 JSON 或纯文本,特别适合写脚本、做巡检和整理接口数据。
先准备一段示例数据,保存为 users.json:
{
"users": [
{"name": "zhang", "age": 28, "city": "西安", "tags": ["go", "linux"]},
{"name": "li", "age": 35, "city": "北京", "tags": ["python"]},
{"name": "wang", "age": 31, "city": "西安", "tags": []}
]
}
一、取一个字段
最常用的是点号取值:
jq '.users[0].name' users.json
# "zhang"
输出带引号是因为结果仍是 JSON 字符串。想要去掉引号,用 -r 输出原始文本,写进脚本或表格时更方便:
jq -r '.users[0].name' users.json
# zhang
二、遍历数组
.users[] 表示把数组拆开、逐个处理,后面再接字段就是批量取值:
jq -r '.users[].name' users.json
三、按条件过滤
select 相当于筛子,只保留满足条件的元素。找出年龄大于 30 岁的用户:
jq '.users[] | select(.age > 30) | .name' users.json
也可以组合条件,例如只看西安且年龄大于 30 岁:
jq -r '.users[] | select(.city == "西安" and .age > 30) | .name' users.json
四、批量提取并重组
实际工作中很少只要一个字段,更多是把多个字段拼成一行。先用对象重组,再用 @tsv 转成制表符分隔的文本,方便粘贴到表格或继续用 awk 处理:
jq -r '.users[] | [.name, .age, .city] | @tsv' users.json
如果只要名字和第一个标签,还可以用数组下标,注意空数组会返回 null,这时用 // 给默认值:
jq -r '.users[] | [.name, (.tags[0] // "无标签")] | @tsv' users.json
五、三个容易踩的坑
第一,字段不存在时 jq 默认输出 null,先用 has 或 // 判断,避免把 null 当成正常值写进结果。第二,数字和字符串不要混着比较,select(.age > "30") 不会按你想的数值大小比较。第三,管道符 | 的左边是输入、右边是处理,写长表达式时先分段验证,每段输出都对了再往后接。
六、一个实战用法
巡检接口时,经常要从一堆返回里快速确认异常用户。下面的命令一步到位:只列出年龄大于 30 岁的用户姓名和城市,输出纯文本,每行一条:
jq -r '.users[] | select(.age > 30) | "\(.name) \(.city)"' users.json
掌握点号取值、数组展开、select 过滤和 @tsv 重组这四招,日常绝大多数 JSON 处理就不需要再写临时脚本了。先在小数据上试通,再把表达式放进正式脚本,遇到格式变化时也更容易定位问题。
- 点赞
- 收藏
- 关注作者
评论(0)