本文要点
jq三层功能一学就会:格式化实时 JSON、按路径取字段、管道拼接做过滤/排序/求和,是curl调试 API 的黄金搭档;jq .让乱成一团的 JSON 秒变缩进清晰的层级结构,配-c还能反向压成单行;- 字段取值用
.servers[].name一路点下去,-r去掉引号输出纯文本,keys、length看结构看数量; select(.status == "running")按条件筛行,sort_by(.cpu)排序,add求和,字符串拼接能制表;- 最实用场景:
curl -s url | jq '...'直接在终端把 API 返回的 JSON 抽出我们想要的字段,不必再手动找。
为什么需要 jq
打开一个真实 API 接口,返回的 JSON 往往是几百行、层层嵌套、挤在一团里。我们用眼睛很难直接从里面找出「核心限制还剩几次」「哪台机器还活着」,更别说在脚本里自动处理了。
jq 就是干这个的——它是一个命令行下的 JSON 处理器,能帮你完成三件事:
- 看:把乱成麻绳的 JSON 排版成清晰的层级结构;
- 取:按路径把某个字段的值抽出来;
- 算:像管道一样把多个步骤串起来,做过滤、排序、求和、制表。
它和文本三剑客里的 grep/sed/awk 定位不同:那三位处理的是任意文本,而 jq 天生理解 JSON 结构,所以处理配置文件、云厂商 API 返回、日志里的 JSON 行时,比正则匹配清爽得多。它在绝大多数 Linux 发行版仓库里都有,安装只需要一条命令:
# Debian/Ubuntu
apt install -y jq
# CentOS/RHEL
yum install -y jq方便起见,下面所有例子都用同一个小型「服务器清单」JSON 来演示,你可以照抄到自己的环境里跟着做:
{
"servers": [
{"name": "web01", "region": "cn-hongkong", "ip": "47.238.230.124", "status": "running", "cpu": 8, "uptime_days": 120},
{"name": "db01", "region": "cn-shanghai", "ip": "47.100.85.66", "status": "running", "cpu": 16, "uptime_days": 320},
{"name": "cache01", "region": "ap-singapore", "ip": "13.212.77.9", "status": "stopped", "cpu": 2, "uptime_days": 0},
{"name": "backup01", "region": "cn-hangzhou", "ip": "121.40.50.8", "status": "running", "cpu": 4, "uptime_days": 200}
],
"owner": "Astarry",
"total": 4
}格式化:让 JSON 变得可读
先看它最基础也最高频的用途——看懂一份 JSON。任何 JSON 输入,只要丢给 jq . 就会从「一行挤到底」变成「按缩进排好」:
echo '{"a":1,"b":[1,2]}' | jq不带表达式时 jq 默认执行 .(取整个输入),并把结果按层级美化输出:
{
"a": 1,
"b": [
1,
2
]
}反过来,想让 JSON 变成单行、方便写进日志或传给下一个命令,用 -c(compact):
echo '{"a":1,"b":[1,2]}' | jq -c
# 输出: {"a":1,"b":[1,2]}对一份较大的清单文件,jq keys 能一眼列出顶层有哪些键,帮你快速摸清结构;jq '.servers | length' 则直接告诉你数组里有多少元素:
jq keys /tmp/servers.json
jq -r .owner /tmp/servers.json
jq '.servers | length' /tmp/servers.json输出依次是顶层键 owner、servers、total,取到的 owner 值 Astarry,以及服务器总数 4:

取值:点号一路点进去
jq 的核心语法就是点号路径,跟 JS 里访问对象几乎一样。取 owner 字段就是 .owner,取服务器数组第二个元素就是 .servers[1],再取它的名字就是 .servers[1].name。
默认情况下 jq 输出的是带引号的 JSON 字符串("web01")。在脚本里要想拿到纯文本,加 -r(raw)去引号:
jq -r '.owner' /tmp/servers.json # 输出 Astarry,不带引号[] 是所有数组元素的意思,配合点号可以"横着扫"整批对象。例如取所有服务器的名字:
jq -r '.servers[].name' /tmp/servers.json
# web01
# db01
# cache01
# backup01取字段还能计算:想统计所有服务器 CPU 核数之和,先把 .servers[].cpu 收集进数组(外层加 []),再用 add 求和:
jq '[.servers[].cpu] | add' /tmp/servers.json # 输出 30过滤与排序:条件筛选出想要的行
.servers[] 会吐出所有服务器,可很多时候我们只关心满足条件的那几台——比如「还跑着的机器」。这要用 select(条件):
jq '.servers[] | select(.status == "running") | .name' /tmp/servers.json它会像 grep 那样把数组过滤一遍,只留下 status 是 running 的元素,再取它们的名字,得到 web01、db01、backup01(cache01 已被排除)。
排序用 sort_by,比如按 CPU 核数从低到高排列,并只留下 name 和 cpu 两个字段重新构造成小对象:
jq -c '.servers | sort_by(.cpu) | .[] | {name, cpu}' /tmp/servers.json
# {"name":"cache01","cpu":2}
# {"name":"backup01","cpu":4}
# {"name":"web01","cpu":8}
# {"name":"db01","cpu":16}如果你只想从数组里挑出一个元素,比如取第一台机器然后重组字段名,可以这样写:
jq '.servers[0] | {host: .name, cores: .cpu}' /tmp/servers.json
# { "host": "web01", "cores": 8 }上面这些过滤、排序、重组、求和的组合用法:

字符串拼接:把 JSON 变表格
jq 支持用 \() 把字段值插进字符串,用 \t 表示制表符,于是很轻松就能把结构化 JSON 变成一格一格的表格——这在"把 API 结果汇总打印给人看"时格外好用:
jq -r '.servers[] | "\(.name)\t\(.status)\t\(.cpu)\t\(.region)"' /tmp/servers.json输出不再是 JSON,而是对齐的文本表格:
web01 running 8 cn-hongkong
db01 running 16 cn-shanghai
cache01 stopped 2 ap-singapore
backup01 running 4 cn-hangzhou把过滤和拼接组合起来,就得到一张"只包含在跑机器"的清单:
jq -r '.servers[] | select(.status == "running") | "\(.name)\t\(.status)\t\(.cpu)"' /tmp/servers.json过滤 + 字符串拼接成表的示例:

实战:curl + jq 解析 API 响应
jq 最常见的使用场景,是接在 curl 后面直接解析返回的 JSON。curl -s 去静默地拉 API 数据,| 交给 jq(jq 会读标准输入),jq 再只抽出我们想要的字段。一条命令搞定,不用把 JSON 存下来再人工翻找。
以 GitHub 的限流接口为例,它返回当前每小时剩余请求次数:
curl -s 'https://api.github.com/rate_limit' | jq -r '.resources.core.limit, .resources.core.remaining'直接在终端看到两个数字(比如都是 60,即上限 60、还剩 60),写巡检脚本时想判断"剩余次数会不会掉到 0",抓这个值就对了:

类似的思路可以套在任何返回 JSON 的接口上——查云服务器状态、查天气、查快递、查区块链价格,都是 curl -s url | jq '要的路径'。配合我们之前讲过的 《curl 命令行:从文件下载到 HTTP 接口调试》,这一套足以应对绝大多数"命令行里顺手调接口"的需求。
小结
jq .负责把 JSON 排版成可读结构,-c反向压成单行,keys/length快速摸清结构;- 点号路径
.servers[].name按路径取值,-r去掉引号拿纯文本,[.x] | add能求和; select(条件)过滤行、sort_by排序、\()字符串插值,能把 JSON 变成给人看的表格;- 最高频组合是
curl -s url | jq '...'——在终端直接抽出 API 返回里的关键字段; - jq 理解 JSON 结构,比用正则硬拆可靠得多,是运维脚本里处理接口返回的不二之选。
评论 (0)
暂无评论,快来抢沙发吧!