yq 格式化表达式:用 .yq 表达式文件编写可执行、可注释的 YAML/JSON 处理脚本
2026/9/14 16:54:15 网站建设 项目流程

yq 格式化表达式:用 .yq 表达式文件编写可执行、可注释的 YAML/JSON 处理脚本

【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq

本文讲解 yq 的"格式化表达式"(Formatting Expressions)特性:把 yq 表达式放入带 shebang 的.yq文件中,利用空行和#注释组织复杂表达式,并可直接执行为可执行脚本。读完本文,你将掌握.yq表达式文件的完整写法(含行内注释、管道续行)、shebang 行内携带命令行标志(如#! yq -oj)的技巧、--from-file等价调用方式,以及 yq 源码中识别和加载表达式文件的底层机制。

什么是格式化表达式

v4.41 起,yq 支持把表达式放进.yq文件中编写。这一特性面向的场景是:当一条表达式过长、由多个操作符管道串联、或者需要团队内评审与版本管理时,直接写在 shell 命令行里既难读又难维护。使用表达式文件后,你可以:

  • 空行分隔表达式的逻辑段落;
  • #注释行解释"这段表达式为什么这样写";
  • 行尾注释对单行操作做局部说明;
  • 将文件chmod +x直接作为可执行程序执行
  • 在 shebang 行中固定命令行标志,让文件"自带参数"。

该特性的官方文档页面由文档头文件 formatting-expressions.md 加上测试驱动的生成内容组成,完整页面见 formatting-expressions.md,其内容正是由 formatting_expressions_test.go 中的场景断言自动生成的——这保证了文档示例与实际行为始终一致。

编写表达式文件:空行、注释与管道续行

先看官方文档给出的标准示例。给定输入文件sample.yaml

a: b: old

再写一个名为update.yq的表达式文件:

#! yq # This is a yq expression that updates the map # for several great reasons outlined here. .a.b = "new" # line comment here | .a.c = "frog" # Now good things will happen.

这段文件体现了格式化表达式的三个核心要素:

  1. shebang 行#! yq:声明该文件由 yq 解释执行;
  2. #注释:独立成行的注释(如开头两行和结尾一行)用于描述整体意图;表达式行末尾的# line comment here是行尾注释;
  3. |管道符开头续行.a.c = "frog"前缀|表示与上一行表达式管道串联,等效于单行写法.a.b = "new" | .a.c = "frog",但分两行书写后可以逐行注释、逐段 review。

赋予执行权限后直接运行:

./update.yq sample.yaml

输出:

a: b: new c: frog

注意细节:b被原地更新为new,同时新增c: frog,输入文档的其余结构保持不变。

直接执行表达式文件:shebang 与可执行权限

文档明确指出:表达式文件可以直接执行,但必须先把文件设为可执行chmod +x)。这一点在仓库的验收测试 shebang.sh 中得到验证——它生成如下最小可执行文件:

#!./yq .a.b

执行chmod +x test.yq后,运行./test.yq test.yml(输入为a: {b: apple})应输出apple。仓库根目录本身也保留了一个真实的示例文件 test.yq,内容正是#!./yq.a.b两行,可以作为最小模板参考。

在 shebang 行中携带命令行标志

表达式文件的 shebang 行不仅可以写#! yq,还可以跟随命令行标志,例如:

#! yq -oj

此时对同样的update.yq执行./update.yq sample.yaml,输出即为带缩进的 JSON:

{ "a": { "b": "new", "c": "frog" } }

这里-oj等价于--output-format json加缩进参数(-j是输出 JSON 的标志)。文档特别强调:shebang 行中的标志只在直接执行文件时生效。如果你的 yq 版本较旧或不支持这一行为,等效做法是在调用时显式传标志(如yq -o json --from-file update.yq sample.yaml),或在 CI 中包装调用。

从源码结构看,输出标志由 root.go 中定义的-o/--output-format-j/--tojson(已废弃,提示改用-o=json)等 cobra 持久标志驱动,shebang 文件被内核直接执行时,内核会把#!行剩余部分作为 yq 的命令行参数展开,因此-oj等短标志组合均可原样使用。

注释掉表达式,以及--from-file等价方式

注释语法同时也是"临时禁用某行表达式"的手段。把上例中的第二行操作注释掉:

#! yq # This is a yq expression that updates the map # for several great reasons outlined here. .a.b = "new" # line comment here # | .a.c = "frog" # Now good things will happen.

此时文档中的说明指出:c不再被设置为frog。调用方式改为显式地把表达式文件传给--from-file标志:

yq --from-file update.yq sample.yml

输出只剩:

a: b: new

文档同时强调:--from-file加载表达式文件,与直接执行该文件没有区别。这一等价性在仓库中有多处印证:

  • --from-file标志在 root.go 中注册,描述为 "Load expression from specified file",并被标记为文件路径类标志以启用文件名补全;
  • 验收测试 basic.sh 验证了./yq --from-file instructions.txt test.yml -o=j -I=0./yq ea --from-file ...(evaluate all 子命令)两种调用下,文件表达式的行为一致;
  • 发布记录 release_notes.txt 显示,--from-file于 4.22.1 版本引入(#1120),而"格式化表达式"(空行 + 注释的多行书写形态)则是 v4.41 起的能力,使用时请确认版本前提。

源码级原理:yq 如何识别并加载 .yq 文件

理解 yq 处理表达式文件的完整调用链,有助于排查"为什么我的表达式没生效"这类问题。核心逻辑在 utils.go 的processArgs函数中(约 L280-L307):

  1. 自动识别.yq后缀文件:如果未显式指定--from-file,且第一个参数是一个存在的文件、文件名以.yq结尾,yq 会将其直接当作表达式文件处理,并把它从参数列表中移除——即yq update.yq sample.yaml等价于yq --from-file update.yq sample.yaml。源码中的调试日志也写明 "Assuming arg %v is an expression file";
  2. 读取并规整换行符:随后通过os.ReadFile读入文件内容,并执行strings.ReplaceAll(..., "\r\n", "\n"),把 Windows 风格的 CRLF 换行统一为 Unix 换行。也就是说,在 Windows 上编辑的.yq文件不需要额外转换即可在 yq 中正常工作;
  3. 兜底表达式推断:若加载文件后表达式仍为空,yq 会检查剩余第一个参数——如果不是文件且不是-,则把它推断为命令行表达式。这解释了为什么 root.go 还保留了--expression标志:当 yq 的参数探测把本应是表达式的字符串误判为文件时,可用它"强制指定表达式参数"。

相关全局变量(expressionFileforceExpression等)声明在 constant.go,与--from-file--expression两个标志一一对应。

验证与回归:这个特性如何被测试保证

格式化表达式的正确性由两层测试覆盖:

  • 行为断言测试:formatting_expressions_test.go 中的formattingExpressionScenarios定义了四个场景——带注释的表达式文件、shebang 直接执行(scenarioType: "shebang")、shebang 携带-oj标志输出 JSON(shebang-json)、注释掉| .a.c = "frog"后只剩b: new(对应--from-file路径)。TestExpressionCommentScenarios对每个场景执行真实的解码-求值-编码流程并断言输出,与本文示例中的预期输出逐字对应;
  • 文档生成:同一测试文件中的documentExpressionScenario会把场景渲染成 Markdown(shebang 场景渲染为./update.yq sample.yaml,其余渲染为yq --from-file update.yq sample.yml),写入 usage 文档目录,再由 copy-docs.sh 同步到外部文档站点。因此官方文档示例与测试用例是同一份事实来源,示例不存在"文档漂移"问题。

小结与使用建议

  • 把超过一行的复杂表达式移入.yq文件,用空行分段、#注释说明意图,|开头表示管道续行;
  • 需要脚本化时chmod +x文件并在首行写#! yq(或直接执行时把内核参数写为#! yq -o json等);shebang 标志仅在直接执行时生效;
  • 在 CI 或无法依赖 shebang 的环境中,统一使用yq --from-file expr.yq input.yaml,两者行为等价;
  • .yq后缀文件作为第一参数时会被自动识别为表达式文件,跨平台换行符问题由 yq 内部统一处理;
  • 版本前提:--from-file需 4.22.1 及以上,多行格式化表达式(空行与注释书写形态)需 4.41 及以上,使用前请核对 release_notes.txt 中的对应版本条目。

【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询