简介
jq
是一个命令行 JSON
处理器,允许解析、过滤、转换和格式化 JSON
数据,提取特定字段或重构 JSON
,高效使用 JSON
中的 API
或配置文件。
安装
Debian/Ubuntu
sudo apt install jq
CentOS/RHEL
sudo yum install jq
或
sudo dnf install jq
macOS(Homebrew)
brew install jq
基础语法
jq '<filter>' <file_or_input>
常用选项
-r
:输出原始字符串(去除JSON
引号)-c
:紧凑输出(不格式化),即去除不必要空格--slurp
:将输入合并为单个JSON
数组--arg
:传递外部变量到过滤器--raw-input
:将输入视为原始文本(非JSON
)-n
:不使用输入数据(需手动读取)-S
:按键名排序对象字段--tab
:使用制表符缩进(美化输出)--arg name value
:定义变量,供过滤器使用-M, --monochrome-output
:禁用彩色输出-j, --join-output
:输出不换行,适合处理多行输出
基本过滤器
.
: 表示整个输入JSON
。.key
: 访问对象的字段(例如.name
提取字段name
的值)。[]
: 访问数组元素(例如.items[0]
提取数组第一个元素)。. | select(condition)
: 过滤数据,基于条件选择(例如.[] | select(.age > 30)
)。. | map(transform)
: 对数组中的每个元素应用转换(例如map(.price * 2)
)。. | length
: 获取数组长度或字符串长度。. | keys
: 获取对象的键列表。. | sort_by(field)
: 按指定字段排序数组。. | group_by(field)
: 按字段分组。. | to_entries
: 将对象转换为键值对数组。. | join(",")
: 将数组元素连接为字符串。
过滤器语法详解
基础操作
- 格式化输出:
cat data.json | jq '.' # 美化输出 JSON
输出效果:
{
"name": "Alice",
"age": 30,
"hobbies": ["reading", "hiking"]
}
- 选择字段:
jq '.[].name' data.json # 提取数组所有元素的 name 字段
- 条件过滤:
jq '.[] | select(.age > 25)' data.json # 过滤年龄大于25的对象
- 多字段组合:
jq '.[] | {name, city}' data.json # 组合 name 和 city 字段
- 新增字段:
jq '.[] | .country = "USA"' data.json # 添加 country 字段
- 删除字段:
jq 'del(.[].city)' data.json # 删除所有元素的 city 字段
- 数组映射:
jq 'map(.age * 2)' data.json # 所有年龄翻倍
- 排序与切片:
jq 'sort_by(.age) | .[:2]' data.json # 按年龄升序取前2个元素
- 逻辑运算:and, or, not
jq 'select(.age > 20 and .city == "Beijing")' data.json
- 内置函数:
jq 'length' data.json # 数组长度
jq 'keys' data.json # 对象键名列表
jq 'group_by(.city)' data.json # 按城市分组
- 字段访问:
echo '{"user": {"name": "Alice", "age": 30}}' | jq '.user.name'
# 输出:"Alice"
- 数组索引:
echo '[1, 2, 3]' | jq '.[1]' # 输出:2
- 迭代数组:
echo '[{"id":1}, {"id":2}]' | jq '.[].id' # 输出:1 和 2
- 多字段选择:
echo '{"name": "Alice", "age": 30}' | jq '{name, age}'
# 输出:{"name": "Alice", "age": 30}
条件与逻辑
- 条件过滤(
if-else
):
echo '30' | jq 'if . > 18 then "Adult" else "Child" end'
# 输出:"Adult"
- 逻辑运算符:
echo '{"age": 20}' | jq 'select(.age >= 18 and .age <= 60)'
# 输出:{"age": 20}
字符串与数学操作
- 字符串拼接:
echo '{"name": "Alice"}' | jq '"Hello, " + .name' # 输出:"Hello, Alice"
- 数学运算:
echo '{"x": 5, "y": 3}' | jq '.x * .y' # 输出:15
高级操作
- 递归下降(…):
echo '{"a": {"b": [1, 2]}}' | jq '.. | numbers?' # 输出:1 和 2
- 自定义函数:
echo '5' | jq 'def pow(n): . ^ n; pow(3)' # 输出:125
- 合并数据(+):
echo '{"a":1} {"b":2}' | jq -s '.[0] + .[1]' # 输出:{"a":1, "b":2}
用法示例
格式化打印 JSON(彩色、缩进)
cat data.json | jq .
jq '.' fruit.json
curl http://api.open-notify.org/iss-now.json | jq '.'
提取指定字段
cat data.json | jq '.name'
提取嵌套字段
cat data.json | jq '.user.address.city'
从数组里面选择对象
cat data.json | jq '.users[] | select(.age > 30)'
获取对象数组中特定键的所有值
cat data.json | jq '.users[].name'
过滤并输出为新的 JSON 数组
cat data.json | jq '[.users[] | select(.active == true)]'
修改 JSON(添加或更改键)
cat data.json | jq '.users[] += {"role": "guest"}'
将输出格式化为原始字符串(删除引号)
cat data.json | jq -r '.users[].name'
从命令行使用(无需文件)
echo '{"key": "value"}' | jq '.key'
使用管道组合多个过滤器
cat data.json | jq '.users[] | select(.active == true) | .name'
将多个键放入一个新对象中
cat data.json | jq '.users[] | {name, email}'
使用变量
name="John"
cat data.json | jq --arg name "$name" '.users[] | select(.name == $name)'
统计元素
cat data.json | jq '.users | length'
结合 diff 比较 json 文件
diff <(jq -S . file1.json) <(jq -S . file2.json)
合并多个 JSON 对象
echo '{"a":1} {"b":2}' | jq --slurp '.'
# 输出:{"key": "new_value"}
遍历数组
jq '.items[]'
根据条件选择项目
jq '.users[] | select(.age > 30)'
使用 reduce 进行聚合
jq 'reduce .[] as $item (0; . + $item.value)'
使用walk进行递归遍历
jq 'walk(if type == "string" then ascii_downcase else . end)'
传递变量
jq --arg var "new_value" '.key = $var' <<< '{"key": "old_value"}'
# 输出:{"key": "new_value"}
提取 API 响应的特定字段
curl -s https://api.example.com/users | jq '.[].email'
过滤日志中的错误信息
cat logs.json | jq 'select(.level == "ERROR") | .message'
格式化 JSON 文件
jq '.' input.json > formatted.json
重命名字段
echo '{"old_name": "Alice"}' | jq '{new_name: .old_name}'
# 输出:{"new_name": "Alice"}
处理流式 JSON(–stream)
解析大型或流式 JSON
文件:
jq --stream 'select(length==2)' large.json
定义可复用的函数库:
# math.jq
def sqrt: . ^ 0.5;
# 使用
echo '16' | jq 'import "math" as math; math::sqrt'
正则表达式匹配(test)
echo '"alice@example.com"' | jq 'test("@example.com$")' # 输出:true
调试过滤器(debug)
echo '{"data": [1, 2]}' | jq '.data | debug | .[]'
删除指定字段
jq 'del(.address)' data.json
切片
echo '[1,2,3,4,5,6,7,8,9,10]' | jq '.[6:9]'
返回长度
jq '.fruit | length' fruit.json
批量修改配置文件
jq '.config.timeout = 30' settings.json > tmp.json && mv tmp.json settings.json
生成新的 JSON 对象
jq -n '{"new_field": "value"}'
将用户数据转换为新的结构
jq '.users | map({"full_name": .name, "details": { "age": .age, "location": .city }})' data.json