何时使用
适用场景:
- 解析 API、CLI 工具(AWS、GitHub、kubectl、docker)或日志文件输出的 JSON。
- 转换 JSON 结构:重命名键、扁平化数组、按字段分组、构造新对象。
- 在 bash 脚本或一行命令里嵌入 jq。
- 需要解释一段复杂 jq 表达式的含义。
不该用的边界:
- jq 只读,无法写文件或执行命令;需要落盘/改文件请用其他工具。
- 输入不是 JSON(如纯文本、CSV、YAML)时不适用,先转换或改用 awk/yq 等。
- 不能替代环境相关的校验、测试或专家复核;缺少输入、权限或成功标准时先澄清。
步骤
- 先用
jq 'keys'或jq '.'探查实际结构与字段名(JSON 大小写敏感)。 - 用
.field、.[]、.[i]定位数据,用管道|逐级组合过滤器。 - 用
select(...)过滤、map(...)/{...}转换、add/group_by聚合。 - 输出给 shell 变量或下游命令时加
-r去引号;NDJSON 管道用-c。 - 注入外部变量一律用
--arg(字符串)/--argjson(数字、布尔、JSON),切勿把 shell 变量直接拼进过滤器字符串。
指令
- 取字段 / 嵌套:
jq '.name'、jq '.user.email' - 数组:索引
jq '.[1]'、切片jq '.[2:4]'、遍历jq '.[]' - 过滤:
jq '[.[] | select(.role == "admin")]',多条件select(.active == true and .score >= 80) - 转换:
jq 'map(.name)'、构对象jq '[.[] | {user: .name, years: .age}]'、加字段jq '[.[] | . + {senior: (.age > 28)}]' - 聚合:
jq 'add'、jq '[.[].price] | add'、jq 'length'、jq 'max_by(.score)'、jq 'group_by(.status) | map({status: .[0].status, count: length})' - reduce:
jq 'reduce .[] as $x (0; . + $x)' - 格式化(配
-r):插值"\(.name) is \(.age)"、@csv、@tsv、@uri、@base64 - 键与路径:
jq 'keys'、jq 'has("email")'、jq 'del(.password)'、递归取值jq '.. | .id? // empty' - 条件与容错:
if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end、默认值.nickname // .name、容错try .nested.value catch null - 多文件/多行:
jq -s '.' records.ndjson、jq -s 'add' a.json b.json - 进阶:
unique_by(.email)、flatten(1)、transpose、walk(if type=="string" then ascii_downcase else . end)、jq -n 'env.API_KEY'
示例
# 提取字段
echo '{"name":"alice","age":30}' | jq '.name' # "alice"
# 过滤管理员并收回数组
echo '[{"role":"admin"},{"role":"user"},{"role":"admin"}]' \
| jq '[.[] | select(.role == "admin")]'
# 求和一个字段
jq '[.[].price] | add'
# 安全注入 shell 变量(字符串用 --arg,数字用 --argjson)
STATUS="active"
jq --arg s "$STATUS" '[.[] | select(.status == $s)]'
jq --argjson threshold 42 '[.[] | select(.value > $threshold)]'
# 转 CSV(-r 去引号)
jq -r '.[] | [.name, .age, .email] | @csv'
# 对象的数组 -> 数组的对象
# 输入: {"names":["a","b"],"scores":[10,20]}
jq '[.names, .scores] | transpose | map({name: .[0], score: .[1]})'
# 与外部 CLI 串联
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
gh pr list --json number,title | jq -r '.[] | "\(.number)\t\(.title)"'
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
注意事项
- 传给 shell 变量或下游命令时务必加
-r,去掉 JSON 字符串引号。 - 注入变量只用
--arg/--argjson,绝不把 shell 变量直接拼进过滤器字符串(既防注入又防引号问题)。 - 过滤器在脚本中用单引号
jq '.field',避免 shell 提前展开;用双引号易出错。 map(f)比[.[] | f]更易读;用empty丢弃元素而非过滤成null。- 常见坑:
- 输出
null而非预期值:多半是键名拼错,先jq 'keys'查实际字段名。 - 数字被当成字符串:注入数值用
--argjson而非--arg。 - 空数组
add返回null:用add // 0或add // ""兜底。 - 大文件处理慢:试
jq --stream,或改用jstream/gron。
- 输出
- 安全:jq 设计上只读,不能写文件或执行命令;勿把不可信的 JSON 字段值直接拼进 shell 命令,始终加引号或用
--arg。
互见
bash-pro/bash-linux:把 jq 调用封装进健壮的 shell 脚本与管道。github-automation:结合 GitHub CLI 的 JSON 输出使用 jq。
采编自 sickn33/antigravity-awesome-skills(MIT 许可)。