跳转至

jq

来源信息
译文信息

“jq就像处理JSON数据的sed工具。你可以用它来切片、过滤、映射和转换结构化数据,其便捷程度如同用sed、awk、grep等工具处理文本一般。”

https://stedolan.github.io/jq/

jq是一款用C语言编写的JSON处理工具,其理念类似于Perl。由于它是专门为解析JSON设计的,因此具备许多其他文本处理器所没有的实用特性。jq将其程序定义为过滤器,这些过滤器接收JSON数据输入,并输出修改后的JSON数据。虽然看似简单,但jq包含了许多高级功能,在程序化生成附加包文件时极其有用。

本文将从命令行界面角度解释jq的使用。不过jq几乎已经为所有主流编程语言提供了封装器,因此也可以很容易地将jq过滤器集成到Go、JavaScript、Java、Ruby、Python、R等语言中。本文重点讲解面向Minecraft附加包开发的过滤器设计,具体实现方式可以按实际需求选择。

获取jq

官方下载地址为https://stedolan.github.io/jq/download/,下载后的可执行文件可直接使用。

也可以通过系统包管理器安装,但需确保版本不低于jq-1.6。

各语言封装器列表可参考awesome-jq

基础语法

点操作符

最简单的jq过滤器是点号(.),它会原样返回输入JSON。以下面这个资源包清单为例:

::: code-group ```json [资源包清单] { "format_version": 2, "header": { "name": "Example Pack", "uuid": "c35537fa-c79d-fd77-cd89-551b7487abed", "min_engine_version": [1, 16, 0] }, "modules": [ { "type": "resources", "uuid": "199ed596-c0f7-158c-db7d-2da8510690c5", "version": [1, 0, 0] } ] }

:::

### 路径访问

要获取`header`的UUID,可以使用路径表达式`.header.uuid`:

::: code-group
```json [输出结果]
"c35537fa-c79d-fd77-cd89-551b7487abed"
:::

数组操作

访问数组元素的示例:获取最低引擎版本的最后一位。

.header.min_engine_version[-1]

::: code-group ```json [输出结果] 0

:::

### 值修改

使用赋值运算符修改格式版本:

`.format_version = 3`

::: code-group
```json [修改结果]
{
  "format_version": 3,
  "header": {
    ...
  }
}
:::

管道操作

结合map函数对数组元素进行运算:

.header.min_engine_version | map(. + 1)

::: code-group ```json [运算结果] [2, 17, 1]

:::

### 逻辑运算

#### 条件判断

根据`format_version`修改描述文本:

```jq
if .format_version > 1 then
  .header.description = "大版本"
else
  .
end

逻辑组合

复合条件判断示例:

if (.header.version[0] > 1 and (.modules[0].version[0] > 1 | not))
then
  .header.description = "小版本"
end

变量定义

变量作用域会贯穿后续管道:

{hello: "world"} as $var | $var | .hello

内置函数

数学运算

使用幂函数和平方根函数:

{
  "三次幂": pow(.format_version; 3),
  "平方根": .format_version | sqrt
}

映射处理

使用map_values进行全局字符串替换:

.header as $header |
.header = ($header | map_values(
  (select(type == "string") | gsub("示例"; "生产版"))
)) + ($header | map_values(select(type != "string")))

键值转换

使用to_entries重构键值对:

.header | to_entries | map({(value|tostring): key}) | add

递归处理

使用walk清理空值:

walk(if type == "object" then
  with_entries(select(.value != null))
else
  .
end)

自定义函数

函数定义语法示例:

def 加法函数($a; $b):
  $a + $b;

def 无参函数:
  1 + 1;

{
  "组合字符串": 加法函数("合并"; "字符串"),
  "简单计算": 无参函数
}

命令行应用

基础使用格式:

jq '[过滤器]' 输入文件.json > 输出文件.json

带参数调用:

jq -n --arg 变量1 $值1 --arg 变量2 $值2 '
{
  "参数1": $变量1,
  "参数2": $变量2
}'

实战案例

将Java版模型转换为基岩版可附着物模型的完整jq脚本(含UV重映射):

完整转换脚本示例