jq 核心知识点
第一步:准备示例文本文件 (data.json)
请将以下内容保存为一个名为 data.json 的文本文件。这个文件模拟了一个包含系统、服务和状态信息的典型 JSON 响应。
{
  "system_id": "prod-web-cluster-01",
  "timestamp": "2023-10-27T14:30:00Z",
  "region": "us-east-1",
  "status": "HEALTHY",
  "monitoring_enabled": true,
  "load_balancer": {
    "type": "ALB",
    "dns_name": "lb-1234567890abcdef0.us-east-1.elb.amazonaws.com",
    "healthy_hosts": 2,
    "unhealthy_hosts": 0
  },
  "servers": [
    {
      "id": "i-0a1b2c3d4e5f6",
      "ip_address": "10.0.1.15",
      "type": "web",
      "status": "running",
      "cpu_usage_percent": 15.5,
      "memory_mb": 8192,
      "tags": ["primary", "nginx"]
    },
    {
      "id": "i-0f6e5d4c3b2a1",
      "ip_address": "10.0.1.28",
      "type": "web",
      "status": "running",
      "cpu_usage_percent": 22.0,
      "memory_mb": 8192,
      "tags": ["secondary", "nginx"]
    },
    {
      "id": "i-07a8b9c0d1e2f",
      "ip_address": "10.0.2.55",
      "type": "db-replica",
      "status": "stopped",
      "cpu_usage_percent": null,
      "memory_mb": 16384,
      "tags": ["mysql", "readonly"]
    }
  ],
  "active_alerts": null,
  "maintenance_window": {
    "start": "Sun, 03:00 UTC",
    "duration_hours": 2
  }
}
第二步:学习 jq 核心功能及典型任务
jq 的基本工作模式是:读取 JSON 输入 -> 应用过滤器 (filter) -> 输出结果。
基础语法: jq '[过滤器]' [输入文件...]
- 过滤器是用单引号 
' '包裹的jq表达式。 - 如果省略输入文件,
jq会从标准输入读取。 
基础:美化输出与 Identity Filter (.)
最简单的过滤器是 .,它表示整个输入对象,jq 默认会美化输出。
- 任务: 美化并打印整个 JSON 文件。
- 命令:
jq '.' data.json - 解释: 
.是 identity filter,它不做任何改变,只是将输入原样输出,jq默认会进行格式化和着色(如果终端支持)。这是检查 JSON 结构的好方法。 
 - 命令:
 
场景 1: 访问对象字段
使用 .key_name 访问对象的字段。如果 key 包含特殊字符,使用 ."key-name"。
- 
任务: 获取
system_id的值。- 命令:
jq '.system_id' data.json - 解释: 
.system_id选择顶级对象下的system_id字段。 
 - 命令:
 - 
任务: 获取负载均衡器的
dns_name。- 命令:
jq '.load_balancer.dns_name' data.json - 解释: 链式调用,先访问 
load_balancer对象,再访问其下的dns_name字段。 
 - 命令:
 - 
任务: 获取维护窗口的开始时间。
- 命令:
jq '.maintenance_window.start' data.json - 解释: 访问嵌套对象 
maintenance_window的start字段。 
 - 命令:
 
场景 2: 访问数组元素与切片
使用 .key[index] 访问数组元素(索引从 0 开始)。
- 
任务: 获取第一个服务器对象。
- 命令:
jq '.servers[0]' data.json - 解释: 
.servers选择servers数组,[0]选择该数组的第一个元素。 
 - 命令:
 - 
任务: 获取第一个服务器的
ip_address。- 命令:
jq '.servers[0].ip_address' data.json - 解释: 先选择第一个服务器对象,然后从中选择 
ip_address字段。 
 - 命令:
 - 
任务: 获取最后一个服务器对象。
- 命令:
jq '.servers[-1]' data.json - 解释: 支持负数索引,
-1表示最后一个元素。 
 - 命令:
 - 
任务: 获取前两个服务器对象(切片)。
- 命令:
jq '.servers[0:2]' data.json - 解释: 
[start:end]进行切片,包含start索引,不包含end索引。输出会是一个包含这两个对象的数组。 
 - 命令:
 
场景 3: 迭代与提取 (.[], |)
使用 .key[] 将数组或对象的元素/值展开成一个序列流。使用管道符 | 将前一个过滤器的输出传递给下一个过滤器。
- 
任务: 列出所有服务器的
id。- 命令:
jq '.servers[].id' data.json - 解释: 
.servers[]将servers数组中的每个对象输出为一个独立的流。对于流中的每个对象,.id提取其id字段。结果是每个 ID 占一行。 
 - 命令:
 - 
任务: 列出所有服务器的
ip_address和status。- 命令:
jq '.servers[] | {ip: .ip_address, status: .status}' data.json - 解释: 
.servers[]展开数组。管道|将每个服务器对象传递给{ip: .ip_address, status: .status}。这个过滤器为每个输入的服务器对象创建一个新的 JSON 对象,包含ip和status两个键。 
 - 命令:
 - 
任务: 列出第一个服务器的所有标签 (
tags)。- 命令:
jq '.servers[0].tags[]' data.json - 解释: 
.servers[0]选择第一个服务器对象,.tags[]展开其tags数组,将每个标签输出为独立的字符串流。 
 - 命令:
 
场景 4: 构建新的 JSON 对象或数组
使用 {} 构建对象,使用 [] 构建数组。可以在其中嵌套过滤器。
- 
任务: 创建一个只包含
system_id和region的新对象。- 命令:
jq '{sys_id: .system_id, location: .region}' data.json - 解释: 
{key1: filter1, key2: filter2}创建一个新对象。sys_id和location是新对象的键,.system_id和.region是从原始输入中提取值的过滤器。 
 - 命令:
 - 
任务: 创建一个包含所有服务器 IP 地址的数组。
- 命令:
jq '[ .servers[].ip_address ]' data.json - 解释: 
[...]用于构建数组。.servers[].ip_address生成一个 IP 地址流,[]将这个流收集到一个数组中。 
 - 命令:
 - 
任务: 为每个服务器创建一个对象,包含
id和memory_gb(将 MB 转换为 GB,近似)。- 命令:
jq '.servers[] | {id: .id, memory_gb: (.memory_mb / 1024)}' data.json - 解释: 在构建新对象时,可以进行计算。
.memory_mb / 1024计算 GB 值。注意需要括号包围计算表达式。 
 - 命令:
 
场景 5: 使用函数进行过滤 (select())
select(boolean_expression) 函数只保留输入流中使表达式为 true 的元素。
- 
任务: 找出所有状态为 "running" 的服务器对象。
- 命令:
jq '.servers[] | select(.status == "running")' data.json - 解释: 
.servers[]展开数组。select(.status == "running")对每个服务器对象进行判断,只输出status字段等于"running"的对象。 
 - 命令:
 - 
任务: 找出 CPU 使用率大于 20% 的服务器的 ID。
- 命令:
jq '.servers[] | select(.cpu_usage_percent != null and .cpu_usage_percent > 20) | .id' data.json - 解释: 先展开,然后 
select过滤。注意要先检查cpu_usage_percent不为null再进行比较,否则null > 20会出错。最后提取id。 
 - 命令:
 - 
任务: 找出所有包含 "nginx" 标签的服务器的 IP 地址。
- 命令:
jq '.servers[] | select(.tags | contains(["nginx"])) | .ip_address' data.json - 解释: 
contains(element_or_array)检查数组是否包含某个元素或子数组。这里检查.tags数组是否包含"nginx"字符串。 
 - 命令:
 
场景 6: 使用内置函数 (如 length, keys, has)
jq 有许多内置函数。
- 
任务: 计算有多少个服务器。
- 命令:
jq '.servers | length' data.json - 解释: 
length函数可以计算数组的长度或字符串的长度。这里计算servers数组的长度。 
 - 命令:
 - 
任务: 获取顶层对象的所有键。
- 命令:
jq 'keys' data.json - 解释: 
keys函数返回一个包含对象所有键的数组。 
 - 命令:
 - 
任务: 检查顶层对象是否有
active_alerts字段。- 命令:
jq 'has("active_alerts")' data.json - 解释: 
has(key)检查当前对象(这里是顶级对象.) 是否包含指定的键,返回true或false。 
 - 命令:
 - 
任务: 获取所有服务器的 ID 列表(与场景 4 任务 2 类似,但这是另一种常见方法)。
- 命令:
jq '.servers | map(.id)' data.json - 解释: 
map(filter)对输入数组的每个元素应用filter,并返回结果组成的新数组。这里对servers数组中的每个元素应用.id过滤器。 
 - 命令:
 
场景 7: 处理输出格式 (-r, -c)
jq 的输出默认是格式化的 JSON。有时需要原始字符串或紧凑格式。
- 
任务: 获取
system_id的原始字符串值(不带引号)。- 命令:
jq -r '.system_id' data.json - 解释: 
-r(raw output) 选项移除最外层的引号,输出纯文本字符串。这在脚本中赋值给变量时非常有用。 
 - 命令:
 - 
任务: 获取所有运行中服务器的 IP 地址,每个地址占一行,作为原始字符串。
- 命令:
jq -r '.servers[] | select(.status == "running") | .ip_address' data.json - 解释: 结合了过滤和 
-r选项,直接输出 IP 列表,方便后续处理(如ssh循环)。 
 - 命令:
 - 
任务: 将每个服务器对象输出为一行紧凑的 JSON(无换行和多余空格)。
- 命令:
jq -c '.servers[]' data.json - 解释: 
-c(compact output) 选项使每个 JSON 输出项(这里是每个服务器对象)都在单独的一行上,且内部没有不必要的空格。常用于处理 JSON Lines 格式 (ndjson)。 
 - 命令:
 
总结与建议
- 从简单的字段访问 (
.key) 和数组索引 (.[index]) 开始。 - 掌握迭代 (
.[]) 和管道 (|) 的组合,这是jq强大的核心。 - 学习使用 
select()进行条件过滤。 - 练习使用 
{}和[]构建你需要的输出结构。 - 熟悉 
length,keys,map,contains等常用函数。 - 了解 
-r和-c选项在脚本自动化中的重要性。 jq的功能远不止这些,遇到复杂问题时,查阅jq手册 (man jq) 或在线文档/Cookbook 是非常有用的。
现在,你可以在你的电脑上创建 data.json 文件,然后逐一执行上面的命令,观察输出结果。尝试修改过滤器,组合不同的功能,这是掌握 jq 的最佳途径!祝你学习愉快!