折腾侠
工具推荐

jq:命令行 JSON 处理的终极利器

折腾侠
2026/03/29 发布
12约 8 分钟1678 字 / 784 词00

jq:命令行 JSON 处理的终极利器

引言

在当今的软件开发世界中,JSON(JavaScript Object Notation)已经成为数据交换的事实标准。无论是 RESTful API 的响应、配置文件的存储,还是微服务之间的通信,JSON 无处不在。然而,当我们需要在命令行环境中快速查看、过滤、转换或分析 JSON 数据时,传统的文本处理工具如 INLINE_CODE_0INLINE_CODE_1INLINE_CODE_2 就显得力不从心了。

这就是 jq 登场的时刻。作为一个轻量级、功能强大的命令行 JSON 处理器,jq 被誉为"JSON 处理的瑞士军刀"。它不仅能优雅地解析复杂的 JSON 结构,还能执行复杂的转换操作,甚至可以作为简单的计算引擎使用。

本文将深入探讨 jq 的核心功能、安装方法、使用技巧以及实际应用场景,帮助你掌握这个开发者必备的工具。

什么是 jq?

jq 是一个用 C 语言编写的命令行 JSON 处理器,由 Stephen Dolan 于 2012 年创建。它的设计哲学是"做一件事并做好"——专注于 JSON 数据的处理,并提供一种简洁而强大的查询语言。

核心特性

  • 纯命令行工具:无需图形界面,完美集成到 shell 脚本和自动化流程中
  • 流式处理:支持处理大型 JSON 文件,无需一次性加载到内存
  • 函数式编程:提供丰富的内置函数和操作符,支持管道组合
  • 跨平台:支持 Linux、macOS、Windows(通过 WSL 或 Cygwin)
  • 零依赖:单个二进制文件,部署简单

安装指南

macOS

使用 Homebrew 安装是最简单的方式:

Bash
brew install jq

Linux

Ubuntu/Debian:

Bash
sudo apt-get update
sudo apt-get install jq

CentOS/RHEL:

Bash
sudo yum install jq
# 或者使用 dnf(较新版本)
sudo dnf install jq

Arch Linux:

Bash
sudo pacman -S jq

Windows

Windows 用户有以下几种选择:

  1. WSL(Windows Subsystem for Linux):在 WSL 中按照 Linux 方法安装
  2. Chocolatey
    Bash
    choco install jq
    
  3. Scoop
    Bash
    scoop install jq
    
  4. 直接下载二进制文件:从 GitHub Releases 下载预编译的 INLINE_CODE_3 文件

验证安装

安装完成后,运行以下命令验证:

Bash
jq --version

应该输出类似 INLINE_CODE_4 的版本信息。

基础用法

读取 JSON 文件

最简单的用法是直接读取 JSON 文件:

Bash
jq '.' data.json

INLINE_CODE_5 是 jq 的过滤器,表示"输出整个输入"。jq 会自动格式化输出,添加适当的缩进和换行,使 JSON 更易读。

从管道读取

jq 可以从标准输入读取数据,这使其成为管道操作的理想工具:

Bash
curl -s https://api.github.com/users/octocat | jq '.'

访问字段

使用点号访问对象字段:

Bash
jq '.name' data.json
jq '.user.name' data.json

访问数组元素

使用方括号访问数组元素:

Bash
jq '.items[0]' data.json
jq '.items[-1]' data.json  # 最后一个元素
jq '.items[0:3]' data.json  # 切片,前三个元素

高级功能

过滤和选择

select 函数:根据条件过滤数组元素

Bash
# 选择所有年龄大于 25 的用户
jq '.users[] | select(.age > 25)' data.json

# 选择所有状态为 active 的服务
jq '.services[] | select(.status == "active")' data.json

map 函数:对数组每个元素应用转换

Bash
# 将所有价格乘以 1.1(涨价 10%)
jq '.products | map(.price *= 1.1)' data.json

# 提取所有用户名
jq '.users | map(.name)' data.json

递归下降

使用 INLINE_CODE_6 递归遍历整个 JSON 结构:

Bash
# 查找所有名为 "id" 的字段
jq '.. | .id? // empty' data.json

# 查找所有字符串值
jq '.. | strings' data.json

变量绑定

使用 INLINE_CODE_7 关键字绑定变量:

Bash
# 将第一个用户绑定到变量 $first,然后在后续操作中使用
jq '.users[0] as $first | .users[] | select(.age > $first.age)' data.json

自定义函数

使用 INLINE_CODE_8 定义 reusable 函数:

Bash
jq 'def square: . * .; [1, 2, 3, 4] | map(square)' data.json
# 输出:[1, 4, 9, 16]

分组和聚合

group_by:按字段分组

Bash
# 按部门分组员工
jq '.employees | group_by(.department)' data.json

聚合函数

Bash
# 计算总和
jq '[.prices[]] | add' data.json

# 计算平均值
jq '[.scores[]] | add / length' data.json

# 查找最大值
jq '[.values[]] | max' data.json

# 统计数量
jq '.items | length' data.json

实际应用场景

场景一:API 响应处理

调用 REST API 时,快速提取所需数据:

Bash
# 获取 GitHub 用户的仓库名称
curl -s https://api.github.com/users/octocat/repos | jq '.[].name'

# 获取仓库的 star 数并排序
curl -s https://api.github.com/users/octocat/repos | jq 'sort_by(-.stargazers_count) | .[:5] | .[] | {name, stars: .stargazers_count}'

场景二:日志分析

处理 JSON 格式的日志文件:

Bash
# 统计不同级别日志的数量
cat app.log | jq -s 'group_by(.level) | map({level: .[0].level, count: length})'

# 提取所有错误日志
cat app.log | jq 'select(.level == "ERROR")'

# 计算平均响应时间
cat access.log | jq -s '[.[].response_time] | add / length'

场景三:配置文件转换

在不同配置格式之间转换:

Bash
# 从 JSON 提取环境变量格式
jq -r 'to_entries[] | "\(.key | ascii_upcase)=\(.value)"' config.json

# 合并多个配置文件
jq -s '.[0] * .[1]' base.json overrides.json

场景四:数据验证

验证 JSON 结构是否符合预期:

Bash
# 检查必需字段是否存在
jq 'if .name and .email then "valid" else "invalid: missing required fields" end' user.json

# 验证邮箱格式(简单示例)
jq '.email | test("^[^@]+@[^@]+\\.[^@]+$")' user.json

场景五:批量数据处理

处理大型数据集:

Bash
# 从大型 JSON 数组中提取特定字段
cat large_dataset.json | jq '.[] | {id, name, price}' > extracted.json

# 分块处理(每 100 条记录)
cat large_dataset.json | jq -n '[inputs] | .[0:100]'

性能优化技巧

使用 -c 紧凑输出

默认情况下,jq 会格式化输出。使用 INLINE_CODE_9 选项输出紧凑的 JSON,减少文件大小:

Bash
jq -c '.' data.json

使用 -r 原始输出

输出字符串时不带引号,适合生成纯文本:

Bash
jq -r '.users[].name' data.json

使用 -s 滑动输入

将整个输入流读取为数组,适合聚合操作:

Bash
cat multiple.json | jq -s 'add'  # 合并多个 JSON 文件

避免不必要的递归

递归下降 INLINE_CODE_10 虽然强大,但在大型文件上可能很慢。尽量使用明确的路径。

替代方案对比

虽然 jq 是 JSON 处理的佼佼者,但了解替代方案有助于选择最适合的工具:

1. Python + json 模块

优点

  • Python 内置支持,无需额外安装
  • 可以进行复杂的逻辑处理
  • 适合需要编程逻辑的场景

缺点

  • 启动开销大,不适合简单查询
  • 代码冗长,不如 jq 简洁

示例

Python
import json
with open('data.json') as f:
    data = json.load(f)
    print([u['name'] for u in data['users'] if u['age'] > 25])

2. Node.js + jq 替代品

node-jq:Node.js 实现的 jq

优点

  • 与 Node.js 生态系统集成
  • 支持 npm 包管理

缺点

  • 性能不如原生 jq
  • 需要 Node.js 环境

3. yq

yq:类似 jq,但支持 YAML、XML 等多种格式

优点

  • 多格式支持
  • 语法与 jq 兼容

缺点

  • 功能相对 jq 较少
  • 性能略逊

4. 专用工具

  • gron:将 JSON 转换为可 grep 的形式
  • fx:交互式 JSON 查看器
  • jpt:JSON 数据透视工具

最佳实践

1. 始终验证输入

在处理不可信的 JSON 输入时,先验证其有效性:

Bash
jq empty data.json && echo "Valid JSON" || echo "Invalid JSON"

2. 使用错误处理

使用 INLINE_CODE_11 操作符抑制错误,或使用 INLINE_CODE_12 提供默认值:

Bash
jq '.optional_field? // "default_value"' data.json

3. 编写可复用的过滤器

将常用查询保存到文件中:

Bash
# filters.jq
def active_users: .users[] | select(.active == true);
def user_summary: {name, email};

active_users | user_summary

使用:

Bash
jq -f filters.jq data.json

4. 组合小过滤器

遵循 Unix 哲学,组合多个简单过滤器:

Bash
jq '.users[] | select(.age > 25) | .name' data.json

而不是写一个复杂的单行过滤器。

5. 使用颜色输出

在终端中使用颜色提高可读性:

Bash
jq --color-output '.' data.json

学习资源

总结

jq 是每个开发者都应该掌握的工具。它简洁的语法、强大的功能和出色的性能,使其成为处理 JSON 数据的不二之选。无论是日常的 API 调试、日志分析,还是复杂的数据转换,jq 都能提供优雅的解决方案。

记住,工具的价值在于使用。最好的学习方式是从实际工作中遇到的问题出发,逐步积累 jq 的使用技巧。下次当你面对 JSON 数据时,不妨试试 jq,你会发现命令行处理 JSON 也可以如此优雅和高效。

开始你的 jq 之旅吧,让数据处理变得更加简单!


本文介绍了 jq 的核心概念和实用技巧。掌握这些基础知识后,你可以进一步探索 jq 的高级功能,如窗口函数、递归下降优化、以及与其他 Unix 工具的深度集成。

分享到:

如果这篇文章对你有帮助,欢迎请作者喝杯咖啡 ☕

加载评论中...