jq —— JSON 的命令行处理器
jq —— JSON 的命令行处理器
分类:04 文本处理 适用:全平台(jq 1.6 / 1.7) 一句话:解析接口返回、K8s 配置、云厂商 API 输出,把 JSON 变成可读、可筛、可统计的文本。
1. 它解决什么问题
curl回来的 JSON 挤成一行,看不清结构。- 从嵌套 JSON 里取出某个字段做统计。
- 把 JSON 数组转成 CSV/表格。
- 批量改 JSON 配置(改镜像、改副本数)。
2. 基础
echo '{"a":{"b":1}}' | jq . # 格式化输出
jq . file.json # 同上
jq -c . file.json # 紧凑输出(一行)
jq -r .name file.json # 原始字符串(去掉引号)
jq '.a.b' file.json # 取嵌套字段
jq '.items[0]' file.json # 数组第一个
jq '.items[-1]' file.json # 最后一个
jq '.items[1:3]' file.json # 切片
jq '.items[]' file.json # 展开数组
jq '.items[].name' file.json # 取每项字段
jq '.a, .b' file.json # 多个输出
jq '.a | .b' file.json # 管道
jq 'keys' file.json # 键列表
jq 'length' file.json # 长度(数组/字符串/对象)
jq 'type' file.json # 类型
jq 'has("name")' file.json # 是否有键
字段名含特殊字符:
jq '."my-key"' file.json
jq '.data["user name"]' file.json
字段不存在不会报错,返回 null;对 null 取子字段会报错,用 ? 抑制:
jq '.a.b?' file.json
jq '.items[]?.name' file.json
3. 过滤与转换
# select 过滤
jq '.items[] | select(.status == "Running")' pods.json
jq '.items[] | select(.status == "Running") | .metadata.name' pods.json
jq '.[] | select(.age > 30)' users.json
jq '.[] | select(.name | test("^web"))' hosts.json
jq '.[] | select(.tags | index("prod"))' hosts.json
# map 对数组逐项处理
jq 'map(.name)' file.json
jq 'map(select(.enabled))' file.json
jq 'map({name: .name, port: .port})' file.json
# 构造新对象
jq '{name: .metadata.name, ns: .metadata.namespace}' pod.json
jq '[.items[] | {n: .metadata.name}]' pods.json
# 删除字段
jq 'del(.password)' file.json
jq 'del(.items[].secret)' file.json
# 合并
jq '.a + .b' f1.json f2.json # 浅合并
jq -s '.[0] * .[1]' a.json b.json # 深合并(* 递归)
jq -s 'add' a.json b.json # 数组合并成一个
4. 统计与分组
jq 'length' # 元素个数
jq '[.[] | .age] | add' # 求和
jq '[.[] | .age] | add / length' # 平均
jq '[.[] | .age] | max' # 最大
jq '[.[] | .age] | min'
jq 'group_by(.status) | map({status: .[0].status, count: length})'
jq '[.[] | .status] | group_by(.) | map({(.[0]): length}) | add'
jq 'sort_by(.time)' # 排序
jq 'sort_by(.time) | reverse'
jq 'unique_by(.name)' # 按字段去重
jq 'unique' # 完全去重
jq 'to_entries' # {a:1} → [{key,value}]
jq 'with_entries(select(.value != null))' # 过滤空值
jq 'reduce .[] as $x (0; . + $x)' # reduce
5. 输出格式
jq -r '.[] | "\(.name)\t\(.port)"' file.json # 制表符分隔
jq -r '.[] | [.name, .port] | @tsv' file.json # TSV
jq -r '.[] | [.name, .port] | @csv' file.json # CSV
jq -r '.[] | @base64' file.json # base64
jq -r '.token' file.json # 取裸值(脚本用)
jq -j '.name' file.json # 不换行
jq '.items | length' file.json # 直接算长度
jq '.[] | keys' file.json
@tsv / @csv 会自动处理转义,比手拼字符串可靠。
6. 变量与参数
jq --arg name "web01" '.[] | select(.name == $name)' hosts.json
jq --argjson port 8080 '.[] | select(.port == $port)' svc.json
jq --slurpfile cfg cfg.json '. + $cfg[0]' main.json
jq -n --arg a 1 --arg b 2 '{sum: ($a|tonumber) + ($b|tonumber)}'
jq --argjson arr '[1,2,3]' -n '$arr | add'
-n 不读输入,用于构造 JSON;-s(--slurp)把多个输入合成一个数组。
7. 实战场景
7.1 格式化 API 返回
curl -s https://api.example.com/users | jq .
curl -s -H 'Authorization: Bearer x' https://api.example.com/users | jq '.[] | {id, name}'
7.2 从 K8s 输出里取容器镜像
kubectl get pods -A -o json \
| jq -r '.items[] | .spec.containers[] | "\(.image)"' \
| sort | uniq -c | sort -nr
7.3 找出状态异常的 Pod
kubectl get pods -A -o json \
| jq -r '.items[] | select(.status.phase != "Running") | "\(.metadata.namespace)/\(.metadata.name) \(.status.phase)"'
7.4 JSON 转 CSV 给 Excel
jq -r '["name","cpu","mem"], (.[] | [.name, .cpu, .mem]) | @csv' nodes.json > nodes.csv
7.5 批量改 JSON 配置
jq '.spec.replicas = 3' deploy.json > /tmp/new.json && mv /tmp/new.json deploy.json
jq '.image = "app:1.2.3"' deploy.json > tmp && mv tmp deploy.json
jq 'del(.spec.template.spec.containers[].resources.limits)' deploy.json > tmp && mv tmp deploy.json
7.6 处理 JSON Lines(每行一个 JSON)
jq -c 'select(.level == "ERROR") | {t: .time, msg: .msg}' app.jsonl
jq -s 'group_by(.service) | map({service: .[0].service, n: length})' app.jsonl
7.7 默认值处理
jq '.config.timeout // 30' file.json # null/false 时用默认
jq '.items // [] | length' file.json
jq 'if .enabled then "on" else "off" end' file.json
8. 常见坑
- 字段名带
-或空格必须引号:.my-key会被解析成减法。 .[]对null报错:用.[]?。-r只对字符串生效:对象仍会输出 JSON。- 浮点精度:jq 用 IEEE754,金额统计会失真,重要计算用 Python。
- 大文件内存:jq 默认全量读入,几百 MB 会吃满内存,改用
--stream或jq -c逐行。 sort_by对混合类型报错:先统一类型(tostring)。group_by必须先排序(jq 内部会排,但语义上要保证字段存在)。--argjson与--arg混用:前者传 JSON,后者传字符串,类型错会报错。- 中文输出乱码:jq 输出 UTF-8,终端 locale 不对时乱码。
//也会把false当空值:false // 30得到 30,注意业务语义。-e用于脚本判断:输出为false/null时退出码 1,可做断言。- Windows 下引号麻烦:PowerShell 里用单引号包 jq 表达式,双引号包外层。
9. 速查表
jq . # 格式化
jq -c . # 紧凑
jq -r '.a' # 裸字符串
jq '.a.b' # 嵌套
jq '.items[]' # 展开
jq '.items[].name' # 批量取字段
jq 'keys' / 'length' / 'type'
jq '.[] | select(.x == "y")'
jq 'map(.name)'
jq 'group_by(.k) | map({k: .[0].k, n: length})'
jq 'sort_by(.t)'
jq 'del(.p)'
jq '.a = 1' # 赋值
jq --arg v x '.[] | select(.n == $v)'
jq -r '.[] | [.a,.b] | @tsv'
jq -n '{a:1}' # 构造
jq -s 'add' # 合并数组
jq '.x // "default"' # 默认值