jq命令详解
jq命令详解
API 调试、CI 日志、Kuberneteskubectl输出、配置文件巡检——碰到 JSON 时,grep容易误伤引号与嵌套,jq用声明式过滤器直接查询、裁剪、重组 JSON,是命令行下的标配工具。
速览
- 语法:
jq '<过滤器>' file.json或cat file.json | jq '<过滤器>' - 取字段:
.name、.address.city;数组:.items[0]、.items[] - 过滤:
select(.age > 20);构造:{user: .name} - 常用选项:
-r去引号、-c压缩一行、-s多行 JSON 合并为数组 - 表达式必须加引号:
jq '.name'✅,jq .name❌(shell 会拆参数)
核心结论(30 秒版)
- 只看结构→
jq .或jq -C .彩色格式化。 - 提一个字段给脚本→
jq -r '.name'。 - 筛数组→
.items[] | select(.status == "ok")。 - 改字段不改文件→
jq '.age += 1'输出到新文件或管道。 - JSON 用jq,纯文本行用grep;别用 grep 解析 JSON。
速查卡片
jq . 格式化 jq -r '.name' 取字段(无引号,给 shell) jq '.items[]' 展开数组 jq '.items[] | select(.ok)' 筛数组元素 jq 'select(.age > 20)' 筛根对象(单条 JSON) jq '{a: .name, b: .city}' 构造对象 jq '.items | map(.name)' 批量变换 jq -c '...' 一行一条(JSON Lines) jq -e '...' 失败时 exit 1(脚本判断)目录
- 1. 安装与调用
- 2. 示例数据
- 3. 基础用法:取值与遍历
- 4. 过滤 select
- 5. 构造与变换
- 6. 常用内置函数
- 7. 常用选项
- 8. 实战场景
- 9. jq、grep 与 yq
- 10. 常见坑
- 11. 何时不必用 jq
- 12. 延伸阅读
1. 安装与调用
| 平台 | 安装 |
|---|---|
| Linux | apt install jq/dnf install jq |
| macOS | brew install jq |
| Windows | winget install jqlang.jq或 WSL |
jq[选项]'<jq表达式>'文件.jsoncat文件.json|jq'<jq表达式>'curl-sURL|jq'<jq表达式>'2. 示例数据
下文示例统一使用data.json:
{"name":"Alice","age":25,"skills":["jq","bash","python"],"address":{"city":"Beijing","zip":"100000"}}数组场景补充users.json:
{"items":[{"name":"Alice","age":25,"status":"ok"},{"name":"Bob","age":17,"status":"ok"},{"name":"Carol","age":30,"status":"fail"}]}3. 基础用法:取值与遍历
3.1 格式化与类型
| 命令 | 作用 |
|---|---|
jq . data.json | 美化缩进(最常用) |
jq -C . data.json | 彩色输出(TTY 下) |
jq type data.json | 根节点类型 →"object" |
3.2 对象字段与数组下标
jq'.name'data.json# "Alice"jq'.address.city'data.json# "Beijing"jq-r'.name'data.json# Alice (-r 去掉 JSON 引号,适合 shell 变量)jq'.skills[0]'data.json# "jq"jq'.skills[-1]'data.json# "python"jq'.skills | length'data.json# 3字段可能不存在时用//默认值:
jq'.phone // "N/A"'data.json# "N/A"3.3 展开数组与管道
jq'.skills[]'data.json"jq" "bash" "python"对象键值:
jq'keys'data.json# ["address", "age", "name", "skills"]jq'to_entries[] | .key'data.json# "name" "age" "skills" "address" (多行输出)管道|:左侧输出作为右侧输入。
jq'.skills | map(ascii_upcase)'data.json# ["JQ", "BASH", "PYTHON"]4. 过滤 select
区分两种写法:对数组元素过滤前要先
[]展开,select作用在单个元素上;对根对象(整条 JSON 就是一个 object)可直接select(条件),保留或丢弃整份输入。
4.1 数组元素过滤
jq'.skills[] | select(. == "bash")'data.json# "bash"jq'.items[] | select(.status == "ok")'users.json第二条输出两行对象(Alice、Bob)。若写成jq '.items | select(.status == "ok")'则错误——此时.是整个数组,不是元素。
4.2 根对象过滤(单对象 JSON)
jq'select(.age > 20)'data.json年龄 ≤ 20 时 jq 无输出(该条被丢弃)。
4.3 多条件
jq'select(.age > 20 and .name == "Alice")'data.json jq'.items[] | select(.age >= 18 and .status == "ok")'users.json# 仅 Alice5. 构造与变换
5.1 生成新对象
jq'{user: .name, location: .address.city}'data.json{"user":"Alice","location":"Beijing"}5.2 修改字段(不可变风格)
jq'.age += 1'data.json jq'.skills += ["go"]'data.json jq'del(.address.zip)'data.json输出为新 JSON,原文件不变;写回需重定向:jq ... data.json > data.new.json,或jq ... file | sponge file(moreutils)。
5.3 map 批量变换
jq'.items | map({name, adult: (.age >= 18)})'users.json[{"name":"Alice","adult":true},{"name":"Bob","adult":false},{"name":"Carol","adult":true}]6. 常用内置函数
| 函数 | 说明 | 示例 |
|---|---|---|
length | 字符串/数组长度 | .skills | length→3 |
keys | 对象键数组 | keys |
has("key") | 是否含键 | has("name")→true |
map(f) | 数组映射 | map(.name) |
join(sep) | 数组拼字符串 | .skills | join(", ") |
sort/sort_by(.field) | 排序 | .items | sort_by(.age) |
unique | 去重 | unique |
group_by(.field) | 分组 | .items | group_by(.status) |
jq'.skills | join(", ")'data.json# "jq, bash, python"jq'.items | group_by(.status)'users.json# [{"status":"fail",...}, {"status":"ok",...}] 两组7. 常用选项
| 选项 | 作用 |
|---|---|
-r | raw 输出,字符串无引号 |
-c | compact,一行一条 JSON(流式处理友好) |
-s | slurp,多行/多个 JSON 文档读入为数组 |
-C | 彩色 |
-e | 过滤器结果为 false/null 时 exit 1(脚本判断) |
--arg k v | 传入外部变量$k |
--argjson k v | 传入 JSON 变量 |
--stream | 流式解析超大 JSON(进阶,见下) |
# slurp:多个 JSON 文件合并为一个数组jq-s'.'a.json b.json# 外部变量jq--argprefix"user"'{id: ($prefix + "_" + .name)}'data.json# {"id": "user_Alice"}--stream(进阶)
日常 API /kubectl响应无需--stream。仅当单文件数百 MB、无法一次jq .载入时考虑:
# 流式输出 [路径, 值] 对;路径末级为叶子时 length==2jq--stream'select(length == 2)'huge.json|head语义较难,详见 jq 手册 --stream;多数场景用jq -c处理 JSON Lines 即可。
8. 实战场景
8.1 API 提取字段
curl-shttps://api.github.com/users/octocat\|jq'{login, id, public_repos}'8.2 Kubernetes
kubectl get pods-ojson\|jq'.items[] | select(.status.phase != "Running") | .metadata.name'kubectl get pod my-pod-ojson\|jq-r'.spec.containers[].image'YAML 清单常用兄弟工具yq(见 §9)。
8.3 统计与聚合
jq'.items | length'users.json# 3jq'[.items[].age] | add / length'users.json# 24(平均年龄)jq'[.items[] | select(.status=="fail")] | length'users.json# 18.4 CI / 日志一行 JSON
grep'^{'app.log|jq-c'select(.level == "ERROR") | {ts, msg}'CI 脚本建议开头:
set-euopipefail# ...if!jq-e'.build.passed == true'report.json>/dev/null;thenecho"build failed">&2;exit1fi避免jq解析失败或-e判假时被管道静默吞掉。
8.5 与 shell 变量
name=$(jq-r'.name'data.json)ifjq-e'.age >= 18'data.json>/dev/null;thenecho"adult";fi9. jq、grep 与 yq
| 场景 | 工具 |
|---|---|
| 结构化 JSON 取字段、改结构 | jq |
| YAML(K8s manifest、docker-compose) | yq(语法与 jq 高度相似,如yq '.spec.replicas' deploy.yaml) |
| 纯文本日志、非 JSON 行 | grep/rg |
| JSON 里搜子串(应急) | jq -r '.. | strings' | grep foo(笨重) |
错误:curl ... | grep '"name"' # 易匹配错字段、无法处理嵌套 正确:curl ... | jq -r '.name'JSON Lines(每行一个 JSON)常用jq -c或逐行管道。
10. 常见坑
| 坑 | 正确做法 |
|---|---|
jq .name无引号 | shell 拆词 →jq '.name' |
| 输出带引号无法赋变量 | 字符串用-r |
对数组select忘写[] | .items[] | select(...) |
| 修改原文件 | jq 只 stdout →重定向或sponge |
null字段 | //默认值或select(has("x")) |
| 数字与字符串比较 | .id == "123"vs.id == 123类型要一致 |
| CI 中 jq 失败被忽略 | set -euo pipefail+-e |
11. 何时不必用 jq
| 场景 | 更合适的工具 |
|---|---|
| GB 级 JSON ETL、复杂多步关联 | Python / Go / DuckDB;jq 全量读入慢 |
| 复杂业务逻辑、多文件事务 | 应用代码,而非 shell 一行链 |
| 原地改文件 | jq 不直接写盘;需重定向或sponge,易误覆盖 |
| 非 JSON(纯文本、CSV 主场景) | awk/csvkit/ 专用解析器 |
| YAML 为主 | yq或kubectl内置-o json再 jq |
jq 的定位是:命令行上的 JSON 瑞士军刀——快、声明式、管道友好;不是通用数据处理平台。
12. 延伸阅读
| 资源 | 说明 |
|---|---|
| jq 官网 | 手册与教程 |
| jq 手册 jq(1) | 内置函数全集 |
| jq play | 浏览器试过滤器 |
| yq | YAML 处理,jq 语法子集 |
复杂过滤器可先在 jq play 验证,再写入脚本;生产脚本对-e与exit code做好判断,避免静默失败。
收束:jq 把 JSON 当成有类型的数据结构来切,而不是文本行;记住引号包表达式、-r给 shell、数组先[]再 select、map 做重组,足以覆盖日常 API 与运维九成场景。
验证环境:jq 1.7 · yq 4.x · bash · Linux / macOS / WSL