一、 核心基础:精准定位 (Selectors)

与 JSON 交互的起点,解决“数据在哪”的问题。

  • **. (Identity)**:最基础的过滤器,输出原始 JSON 且自动格式化(Pretty-print)。
  • **.field (Object Access)**:通过键名获取值。如果键名包含特殊字符(如横线),需使用引号:."user-name"
  • **.parent.child (Chaining)**:通过点号链接,深度进入嵌套结构。
  • **.[] (Array/Object Iterator)**:
    • 用于数组时:将数组拆解为一个个独立的元素流。
    • 用于对象时:返回对象所有属性的值流(不含键名)。
  • **.[index] (Index Access)**:获取数组特定位置元素,支持负数索引(如 .[-1] 获取末尾元素)。
  • **.[start:end] (Slicing)**:对数组或字符串进行切片,遵循左闭右开原则。

假设有一个名为 data.json 的文件:

1
2
3
4
5
{
"user": "bz",
"tools": ["text", "image", "code"],
"active": true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 漂亮打印
➜ ~/Desktop/sh cat data.json |jq .
{
"user": "bz",
"tools": [
"text",
"image",
"code"
],
"active": true
}
➜ ~/Desktop/sh jq . data.json
{
"user": "bz",
"tools": [
"text",
"image",
"code"
],
"active": true
}

# 打印特定字段
➜ ~/Desktop/sh jq '.user' data.json
"bz"

# 提取数组元素
➜ ~/Desktop/sh jq .tools[] data.json
"text"
"image"
"code"
➜ ~/Desktop/sh jq .tools[1] data.json
"image"
➜ ~/Desktop/sh jq .tools[1:2] data.json
[
"image"
]
➜ ~/Desktop/sh jq .tools[1:3] data.json
[
"image",
"code"
]
➜ ~/Desktop/sh jq .tools[0:3] data.json
[
"text",
"image",
"code"
]
➜ ~/Desktop/sh jq .tools[0:2] data.json
[
"text",
"image"
]

二、 数据重塑:构造与转换 (Construction)

经常需要将原始数据清洗并重新包装,输出给下一个微服务。从杂乱的原始数据中“提取、变形、再包装”,生成完全符合业务需求的新结构。

  • **{} (Object Construction)**:从现有数据中提取字段并重命名:{name: .user, id: .uuid}
  • **[] (Array Construction)**:将多个输出结果收集到一个数组中:[.id, .status]
  • **| (Pipe)**:核心灵魂。将前一个过滤器的输出传给下一个,实现逻辑解耦。
  • **, (Comma)**:并行处理。同一个输入会经过多个过滤器,产生多条独立的输出。
  • **+, -, \*, / (Math & Merging)**:
    • 数字:进行常规算术运算。
    • 对象:obj1 + obj2 用于合并对象(重复键以后者为准)。
    • 数组:arr1 + arr2 用于连接数组。

假设有一个原始数据文件 server.json

1
2
3
4
5
6
7
{
"user": "cloud_admin",
"uuid": "x99-uv2",
"metrics": { "cpu": 45, "mem": 60 },
"status": "online",
"tags": ["production", "v2"]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# {}对象构造,从复杂原始数据中提取几个关键字段,并起个别名
➜ ~/Desktop/sh jq '{name: .user, id: .uuid, ram_usage: .metrics.mem}' server.json
{
"name": "cloud_admin",
"id": "x99-uv2",
"ram_usage": 60
}

# []数组构造,将多个独立字段值放到一个数组,方便后续遍历。
➜ ~/Desktop/sh jq '[.uuid, .status]' server.json
[
"x99-uv2",
"online"
]

# | 它让 jq 具有了流式处理能力,就像 Bash 的管道一样,把前面的结果喂给后面。
➜ ~/Desktop/sh jq '.tags[0]| ascii_upcase' server.json
"PRODUCTION"
➜ ~/Desktop/sh jq '.tags|.[0]| ascii_upcase' server.json
"PRODUCTION"

# , 多个不相关的字段,它们会作为多个独立的结果输出(不是一个对象)。
➜ ~/Desktop/sh jq '.user, .metrics.cpu' server.json
"cloud_admin"
45
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 数值运算
➜ ~/Desktop/sh jq '100 - .metrics.cpu' server.json
55

# 对象合并 在保持原有数据不变的基础上,动态追加一个“地区”字段。
➜ ~/Desktop/sh jq '. + {region: "us-east-1"}' server.json
{
"user": "cloud_admin",
"uuid": "x99-uv2",
"metrics": {
"cpu": 45,
"mem": 60
},
"status": "online",
"tags": [
"production",
"v2"
],
"region": "us-east-1"
}

# 数组相减 剔除不需要的标签。
➜ ~/Desktop/sh jq '.tags - ["v2"] server.json
> ^C
➜ ~/Desktop/sh jq '.tags - ["v2"]' server.json
[
"production"
]


三、 高级逻辑:函数与过滤 (Functions & Logic)

精通 jq 的关键在于利用内置函数处理复杂业务逻辑。

  • **select(boolean_expression)**:数据过滤利器。例如 select(.age > 18) 只保留符合条件的元素。
  • **map(filter)**:针对数组中的每个元素应用过滤器,并返回处理后的新数组。
  • **keys & has("key")**:
    • keys:以数组形式返回对象的所有键名。
    • has("status"):检查对象是否包含特定键,返回布尔值。
  • **length**:通用长度计算。支持字符串长度、数组元素个数及对象键值对数量。
  • **if-then-else-end (Conditionals)**:
    • if .status == 200 then "OK" else "Error" end
  • **try-catch**:处理异常。在解析可能缺失字段或格式不统一的数据时,防止脚本崩溃。

四、 命令行超能力 (CLI Flags)

在 Bash 脚本中,参数决定了 jq 如何与外界交互。

  • -r (Raw Output)必记项。去掉输出字符串的双引号。在 Shell 脚本中给变量赋值时,这是必须选用的。
  • **-c (Compact Output)**:将 JSON 压缩为一行。适合在大规模日志处理或 API 传输中使用,节省带宽和磁盘空间。
  • **-s (Slurp)**:将输入流中的多个独立 JSON 对象读入一个巨大的数组中,方便进行全局统计(如 lengthmax)。
  • **-R (Raw Input)**:将非 JSON 的普通文本行读取为字符串。配合正则函数(test, match)可以将普通日志转化为结构化 JSON。
  • **--arg (Variable Injection)**:从外部 Bash 环境传入变量:jq --arg v "$VERSION" '.version = $v'

五、 实战案例

  • 多层级深度提取
    • jq '.data.items[].metadata | {id: .uid, name: .name}'
    • 场景: 从 K8s API 返回的复杂对象中提取关键元数据。
  • 复杂条件统计
    • jq '[.[] | select(.price > 100)] | length'
    • 场景: 统计电商接口中价格超过阈值的商品总数。
  • 动态修改配置
    • jq '.database.host = "127.0.0.1" | .debug = true' config.json
    • 场景: 在 CI/CD 流水线中根据环境动态更新配置文件。
  • **数据扁平化 (Flatten)**:
    • jq '[.projects[].tasks[]] | unique'
    • 场景: 将嵌套的项目任务列表拉平,并去除重复任务。

小贴士: 当你面对极其复杂的过滤器时,可以将其写入文件(如 logic.jq),然后使用 jq -f logic.jq data.json 执行。这能极大地提高代码的可读性和可维护性。