jq 是一个 Linux / FreeBSD 系统中都可以使用,并且功能非常强大的轻量级的 JSON 处理器,它可以用于解析、转换或者格式化 JSON 文本数据。它提供简洁的查询语法,且可以高效处理 API 响应。

本文将全方面介绍 jq 命令的核心功能和使用技巧,让你更加了解 jq 命令。

jq 命令的语法

如下给出 jq 命令的语法形式:

jq [OPTIONS] FILTER [FILE...]
jq [OPTIONS] -f FILTERFILE [FILE...]
  • FILTER:用于处理 JSON 数据的查询表达式(它是必需的内容)
  • [FILE...]:输入的 JSON 文件(可多个,不指定时,则从标准输入 stdin 读取数据)
  • [OPTIONS]:使用的选项(后面有详细的使用说明)
  • -f FILTERFILE:指定查询表达式的文件

jq 命令查询表达式的详细说明

一、访问 JSON 元素

  1. 使用 . 访问当前根节点对象
  2. 使用 .key 访问根对象的属性,如:.name,访问 name 属性
  3. 使用 .[index] 访问数组元素,如:.[1] 访问数组的第二个元素
  4. 使用 . 连接的嵌套结构,访问嵌套的对象或数组
    1. 示例1:jq '.user.name':访问根对象 user 对象属性的 name 属性
    2. 示例2:jq '.user.address.city':访问根对象 user 对象属性的 address 对象属性的 city 属性
    3. 示例3:jq '.scores[2]':访问根对象 scores 数组属性的第 3 个元素

二、数组的过滤与转换操作

  1. 使用 .[start:end] 对数组进行切片,如: jq '.[2:]' :选择第 3 个元素到最后一个元素
  2. 使用 map(expression) 遍历数组中的元素并根据 expression 转换每一个元素,如: jq 'map(. * 2)' 对每个元素乘2。
  3. 使用 select(condition) 根据 condition 选择特定的元素
    1. 示例1:保留数组中满足 condition 的元素(通常与 map 结合使用), jq 'map(select(. > 10))' :输出大于10 的元素。
    2. 示例2:jq '.[] | select(.age >= 18) | .name' :展开数组,输出数组中每个元素的 age 大于等于 18 的元素。

三、对象的键值对操作

  1. 使用 keys 获取对象的所有键
  2. 使用 has("key") 检查对象是否包含指定键,如: jq 'has("age")' :如果包含 age 属性,则输出 true,否则输出 false
  3. 使用 with_entries(expression) 转换键值对
    1. 实现过程:将对象转为以 {"key": k, "value": v} 为元素的数组,通过 expression 处理后再转换回对象。
    2. 示例1:jq 'with_entries(.value *= 2)':将对象的所有属性的值乘 2。
    3. 示例2:jq 'with_entries(.key |= uppercase)' :将对象的所有属性的键转为大写。

四、条件与逻辑运算

  1. 使用 ==(等于)、!=(不等于)、><>=<= 比较元素大小,如:jq '.age > 25' → 如果 age 大于 25,则输出 true
  2. 使用 and(与)、or(或)、not(非)进行逻辑运算
  3. 使用 if condition then a else b end 进行三目运算

五、常用的函数

1. 常用的字符串函数

  • length:获取字符串长度,如:jq '.name | length'
  • startswith(prefix)/endswith(suffix):检查是否含有特定前缀/后缀,如:jq '.name | startswith("A")'
  • split(sep):分割字符串,如:jq '"a,b,c" | split(",")'
  • uppercase/lowercase:进行大小写转换,如:jq '.name | uppercase'

2. 数组或对象函数

  • length:获取数组长度(jq '.hobbies | length' → 对 ["reading", "hiking"] 输出 2)。
  • empty:返回空数组
  • add:对数组元素进行求和
  • flatten:展开嵌套数组

3. 类型判断函数

  • type:返回元素类型
  • arrays/objects/strings:过滤指定类型的元素,如:jq '.[] | numbers' 只输出数字。

六、使用管道组合运用

管道的作用是:将前一个表达式的输出作为后一个的输入,与 Linux 管道相似。

示例:jq '.user | .name' :先取 user 对象,再从过滤后的对象中选取 name

jq 命令的使用示例

1. 提取 json 数据的属性

如下给出提取 json 数据的特定属性的示例:

echo '{"name":"张三","age":30}' | jq '.name'
  • 查询表达式说明.name 用于提取 name 属性
  • 输出结果"张三"

2. 格式化 JSON 数据

如下给出使用 jq 命令格式化 json 数据的使用示例:

echo '{"name":"张三","age":30}' | jq '.'
  • 查询表达式说明. 表示整个输入对象
  • 功能说明:将输入的 json 数据格式化后输出
  • 输出效果
    {
        "name": "张三",
        "age": 30
    }
    

3. 输出属性具有特定值的数据

如下给出使用 jq 命令输出 active 属性的值为 true 的元素的使用示例:

echo '[{"id":1,"name":"wang"},{"id":2,"name":"li"}]' | jq '.[] | select(.name=="li")'
  • 查询表达式说明
    • .[]:展开数组元素,即:以数组中的每一个元素为查询对象
    • select(.name=="li"):选择每一个元素的 name 属性为 li 的对象
  • 输出结果

    {
        "id": 2,
        "name": "li"
    }
    
  • 适用场景:过滤符合条件的 JSON 数组元素

4. 数据转换与计算

如下给出 jq 命令对数据进行转换的示例:

echo '{"products":[{"name":"A","price":25},{"name":"B","price":40}]}' | jq '.products | map(.price * 1.2) | add'
  • 查询表达式说明
    • map(.price * 1.2):对每个元素的 price 属性乘 1.2
    • add:对计算后的结果数组求和
  • 输出结果78

命令选项详解

如下给出 jq 命令的选项的详细解释说明:

短选项 长选项 说明
-c --compact-output 以无缩进,单行显示的形式输出内容
-r --raw-output 输出原始字符串(非 JSON 格式)
-s --slurp 将输入流读取为单个数组
-f FILE --from-file FILE 从文件读取过滤器
-L PATH --search-path PATH 设置模块搜索路径
--arg VAR VAL - 定义变量(VAL 作为字符串)
--argjson VAR JSON - 定义变量(JSON 作为 JSON 对象)
--slurpfile VAR FILE - 将文件内容读取到变量
--indent N - 设置缩进空格数(默认 2)
--color-output - 启用彩色输出
--monochrome-output - 禁用彩色输出
-M --mono 单色输出(兼容别名)
-S --sort-keys 对象按键名排序
-j --join-output 连续输出无换行
-n --null-input 使用 null 作为输入
-R --raw-input 将输入视为原始字符串
-C --csv 输出 CSV 格式
--tab - 使用制表符缩进
-V --version 显示版本信息

系统安装说明

Debian / Ubuntu

如下给出在 Debian / Ubuntu 系统上安装 jq 命令的说明:

sudo apt update
sudo apt install jq

RHEL / AlmaLinux / Rocky Linux

如下给出在 RHEL / AlmaLinux / Rocky Linux 系统上安装 jq 命令的说明:

sudo yum install jq    # RHEL/CentOS 7
sudo dnf install jq    # RHEL 8+/Alma/Rocky

FreeBSD

如下给出在 FreeBSD 系统上安装 jq 命令的说明:

sudo pkg install jq

结语

jq 命令是处理或者转换 JSON 数据的非常好用的工具,它的核心优势在于:查询效率高,支持管道操作和链式过滤,能够实现 JSON / CSV / TSV 格式文件之间的相互转换。