用 jq 处理 JSON:从查字段到改结构,一篇够用的实战笔记
在日常运维和接口调试中,JSON 几乎无处不在:curl 拿到接口返回、日志里嵌着一层层字段、配置文件本身也是 JSON。直接用肉眼读很容易看错层级,用 Python 写脚本又嫌重,这时 jq 就是最顺手的命令行工具。本文用一个虚构的实例,把最常用的 jq 用法串起来。
一、先看结构,再取字段
假设 resp.json 内容如下:
{"code": 0, "msg": "ok", "data": [{"name": "web-01", "status": "running", "cpu": 72}, {"name": "web-02", "status": "stopped", "cpu": 5}]}
先用 jq . resp.json 美化输出,看清层级;再用点号逐层取字段:jq .code resp.json 得到 0,jq .data[0].name resp.json 得到 “web-01”。数组想全部展开,用 jq '.data[]' resp.json;只想取名字一列,用 jq -r '.data[].name' resp.json,加上 -r 输出的就是不带引号的纯文本,方便接 while read 或 xargs。
二、过滤:只留符合条件的记录
select 是 jq 里最常用的过滤器。找出已停止的实例:jq '.data[] | select(.status == "stopped")' resp.json;找出 CPU 超过 50 的:jq '.data[] | select(.cpu > 50) | .name' resp.json。多个条件用 and、or 组合,例如 select(.status == "running" and .cpu > 50)。配合 length 还能直接计数:jq '[.data[] | select(.status == "stopped")] | length' resp.json。
三、改造输出:只输出想要的形状
原始字段太多时,用对象构造语法重组:jq '.data[] | {实例: .name, 状态: .status}' resp.json。想把数组变成每行一条的简表,用 -c 输出紧凑 JSON:jq -c '.data[] | {name, status}' resp.json,再接 column 或重定向到文件都很方便。需要取所有键名时用 keys,取嵌套路径时用 paths,排查不熟悉的返回结构时特别省时间。
四、和 curl、管道组合使用
最常见的组合是 curl -s https://example.com/api/status | jq .,先确认接口通不通、返回结构对不对,再逐步加过滤。调试时先不加过滤看全量,确认字段名后再收紧条件,避免一开始就写错过滤条件却以为接口没数据。处理大文件时用 jq -c 逐行输出,内存占用更小;只想看前几条时接 | head -n 20,不要先把几十兆结果全打到屏幕上。
五、三个容易踩的坑
第一,Shell 引号:过滤表达式要用单引号包起来,里面再用双引号写字段值,写成 jq ".data" 在很多 Shell 里会先被变量展开。第二,空值:字段可能不存在,用 // 给默认值,例如 jq '.data[] | .cpu // 0' resp.json,避免后续比较报错。第三,中文与转义:默认输出会对非 ASCII 字符转义,想直接看中文加 -r 或用 --ascii-output 之外的默认方式配合终端查看即可,存文件前先确认下游工具能否接受转义形式。
小结
记住四组就够用:. 看结构、.[] 展开数组、select 过滤、{} 重组输出,再加 -r、-c 两个参数。建议找一个真实的接口返回练一遍:先美化、再取字段、再过滤、最后重组输出,十分钟就能把 jq 变成日常排障的固定动作。
- 点赞
- 收藏
- 关注作者
评论(0)