jq 是唯一靠谱的默认选择,因其将 json 当作数据结构而非文本处理,能正确解析引号转义、嵌套、null 等,错误时明确报错而非静默失败。

Shell 本身不支持原生 JSON 解析,硬用 grep/sed/awk 提取字段极易出错——尤其当值含引号、换行、嵌套或逗号时,grep '"key":' 会直接漏掉多行结构或匹配到注释/字符串内部。
为什么 jq 是唯一靠谱的默认选择
它把 JSON 当成数据结构处理,而不是文本流。所有其他方法(比如正则“抠”字符串)在真实运维场景中都属于临时补丁,不是解决方案。
-
jq能正确识别 JSON 的语法边界:引号转义、数组索引、对象嵌套、null值、布尔字面量,都不需要你手动判断 - 错误输入会直接报错退出(如
parse error: Invalid numeric literal),而不是静默返回垃圾结果 - 支持管道链式处理:
curl -s "$API" | jq -r '.data[].id' | head -n 1这种写法稳定可读 - 输出控制灵活:
-r去掉外层引号,-c强制单行,--arg安全传入 Shell 变量
jq 提取字段时最常踩的三个坑
新手常以为写对了路径就万事大吉,但实际运行时卡住,往往是因为:
- 字段名带点或连字符?必须用括号和引号:
.["user.name"]或.["content-type"],不能写.user.name(会被当成两层嵌套) - 数组为空或字段不存在?默认返回
null,jq '.items[0].name'在"items": []时输出null,不是空字符串;加// empty或用try ... catch捕获 - 原始数据是多行 JSON 流(如
curl流式响应)?默认只处理第一个 JSON 对象;加-s(slurp)或用inputs逐个处理
不用 jq 时怎么勉强应付单层 JSON
仅限你完全控制输入格式、且确认 JSON 永远是单行、无嵌套、无转义引号的极简场景(例如生成的配置片段)。
- 用
tr把换行干掉:tr '\n' ' ' - 再用
sed提取键值:sed -n 's/.*"timeout":[[:space:]]*\([^[:space:],}]*\).*/\1/p' - 但注意:
\([^[:space:],}]*\)假设值里不含逗号、花括号、空格——一旦 API 返回"timeout": "30s",这个正则就失效 - 更安全一点的做法是先用
jq -c '.'把任意 JSON 压成单行,再交给文本工具——等于绕一圈又回到jq
从 curl 获取 JSON 后直接进变量,别用 cat + 文件中转
很多人习惯先 curl -o tmp.json 再 jq '.x' tmp.json,其实没必要,还多一个磁盘 I/O 和清理负担。
- 直接管道:
result=$(curl -s "https://api.example.com/status" | jq -r '.status') - 如果要多次提取不同字段,避免重复请求:
json=$(curl -s "$URL"),然后jq -r '.a' - 注意双引号包裹变量:
jq -r --arg url "$API_URL" '.url = $url' ,否则变量内容会被 shell 展开或截断 - 别用
echo $json | jq——未加引号的$json会破坏换行和空格,导致解析失败
真正难的从来不是“怎么写一行命令”,而是“怎么让这行命令在下周、在另一台机器、在 JSON 格式微调后还能跑通”。jq 的表达式可能看起来像密码,但它把不确定性锁死了;而 sed 正则越写越长,越改越不敢动。










