资讯详情

yq 编码与解码运算符完全指南:从 to_json、from_yaml 到 @base64 的嵌入式格式处理实战

📅 2026/9/14 17:56:38 | 华诺云谱 👁 阅读
yq 编码与解码运算符完全指南:从 to_json、from_yaml 到 @base64 的嵌入式格式处理实战
yq 编码与解码运算符完全指南从 to_json、from_yaml 到 base64 的嵌入式格式处理实战【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq导读在真实项目中YAML 文档里经常嵌套着被字符串化的 JSON、YAML、Properties、CSV 甚至 XML 内容例如配置项里存放一段序列化后的 JSON、CI 流水线里嵌入一段 shell 片段。yq 的 Encode/Decode 运算符族正是为这类场景设计的Encode 运算符把管道传入的对象结构编码为指定格式的字符串Decode 运算符则反向把格式化字符串解析回对象结构。本文以 yq 仓库的 encode-decode 官方文档 为骨架结合 operator_encoder_decoder.go 与 lexer_participle.go 的源码实现带你掌握全部 9 种格式的编码/解码用法、indent 参数细节与嵌套字符串的原地更新技巧。核心概念编码与解码是一对可逆操作Encode 运算符负责把对象结构转成字符串Decode 运算符负责把字符串还原成对象结构两者互为逆操作。它们都是标准运算符可以出现在管道pipe的任意位置也可以和赋值运算符、|组合完成解码 → 修改 → 再编码的整段流程。下表是官方文档给出的完整格式速查表两列分别对应各格式的解码与编码入口格式Decode字符串 → 对象Encode对象 → 字符串YAMLfrom_yaml/yamldto_yaml(i)/yamlJSONfrom_json/jsondto_json(i)/jsonPropertiesfrom_props/propsdto_props/propsCSVfrom_csv/csvdto_csv/csvTSVfrom_tsv/tsvdto_tsv/tsvXMLfrom_xml/xmldto_xml(i)/xmlBase64base64dbase64URIuriduriShell—sh注意表内几个细节to_yaml(i)、to_json(i)、to_xml(i)中的(i)表示可以传一个缩进参数而yaml、json、xml这类以开头的速记形式不带参数行为固定详见下文缩进参数一节。解码没有缩进概念因此from_*与*d形式完全等价。Shell 只有编码sh没有对应的解码运算符——因为 shell 字符串无法无歧义地解析回对象。从源码角度看这些运算符在 lexer_participle.go 中被定义为一组带正则的 token 规则例如to_?yaml|yaml→ 使用 2 空格缩进的 YAML 编码encodeWithIndent(YamlFormat, 2)to_?json→ 2 空格缩进的 JSON 编码而json是0 缩进的 JSON 编码encodeWithIndent(JSONFormat, 0)to_?yaml\([0-9]\)→ 通过encodeParseIndent解析括号里的缩进数字这正是to_yaml(8)能被解析的底层原因。这也解释了官方文档Pass in a 0 indent to print json on a single line的说法json在词法层面就固定为indent 0。底层实现encodeOperator 与 decodeOperator编码与解码的运行时逻辑集中在 operator_encoder_decoder.goencodeToStringL34-L46根据目标格式调用configureEncoder构造对应 EncoderconfigureEncoderL12-L32会复制当前全局偏好如ConfiguredYamlPreferences、ConfiguredJSONPreferences再覆盖Indent为本次调用传入的缩进值最后通过Printer输出为字符串。这也是为什么to_yaml输出的字符串与 CLI 顶层-oyaml输出风格一致。encodeOperatorL56-L93遍历每个匹配节点把编码结果生成为!!str类型的标量节点CreateReplacement(ScalarNode, !!str, stringValue)。它还会做两件收尾工作一是当format JSONFormat indent 0或格式为 CSV/TSV 时用chomper正则\n$去掉结尾换行所以json、csv、tsv输出是干净的单行二是借助decoded: key变量记录原始字符串是否以换行结尾从而在解码后重新编码时保持单行/多行形态这正是下文更新单行/多行 YAML 字符串两节行为差异的来源。decodeOperatorL100-L131调用preferences.format.DecoderFactory()获得 Decoder对候选节点的字符串值做decoder.Initdecoder.Decode并把结果节点挂回原 key 与 parent从而替换原字符串值。编码与解码使用的格式注册表在 format.go 中其中 YAML、JSON、Properties、CSV、TSV、XML、Base64、URI 均为可编码也可解码的Format而ShFormat的DecoderFactory为nil这就是 Shell 无解码运算符的源码级原因。JSON字符串化与反序列化JSON 是文档中演示最多的格式因为它最常见于配置里嵌配置的场景。把对象编码为 JSON 字符串给定sample.ymla: cool: thing执行yq .b (.a | to_json) sample.yml输出a: cool: thing b: | { cool: thing }to_json默认使用 2 空格缩进因此输出是带换行的块状标量|。单行 JSONto_json(0) 与 json如果你希望 JSON 输出在一行内例如要直接作为另一个程序的参数传入0缩进yq .b (.a | to_json(0)) sample.yml输出a: cool: thing b: {cool:thing}等价地json就是 0 缩进的速记形式yq .b (.a | json) sample.yml输出与上例完全相同。正如前文源码分析json在词法层即绑定indent 0而to_json绑定indent 2二者语义略有差异速记并不完全等价于无参的to_json。解码 JSON 字符串给定sample.ymla: {cool:thing}执行yq .a | from_json | ... style sample.yml输出cool: thing这里... style是 style 运算符 的递归形式用于清除 JSON 解码后残留的双引号JSON 字符串节点默认带双引号样式。官方文档特别提醒JSON 是 YAML 的子集from_json解码结果在语法上合法但若要得到地道的 YAML 观感建议接上 style 运算符清理。仓库测试 operator_encoder_decoder_test.go 以表格驱动方式逐一验证了这些场景。YAMLto_yaml 的缩进控制与原地更新编码为 YAML 字符串默认 2 空格给定sample.ymla: cool: bob: dylan执行yq .b (.a | to_yaml) sample.yml输出a: cool: bob: dylan b: | cool: bob: dylan文档明确指出to_yaml的缩进默认为 2与configureEncoder中prefs.Indent indent的默认值 2 一致。自定义缩进to_yaml(8)缩进作为第一个参数传入yq .b (.a | to_yaml(8)) sample.yml输出a: cool: bob: dylan b: | cool: bob: dylan注意b的值依然是 YAML 块标量只是内嵌 YAML 的每级缩进变成了 8 空格——这在生成对齐美观的嵌套配置模板时非常实用。解码 YAML 字符串给定sample.ymla: foo: bar执行yq .b (.a | from_yaml) sample.yml输出a: foo: bar b: foo: bar更新多行内嵌 YAML.a | (from_yaml | ... | to_yaml)这是 encode/decode 家族最常用的实战组合先解码、再修改、最后重新编码且用|更新运算符原地写回。给定多行块标量a: | foo: bar baz: dog执行yq .a | (from_yaml | .foo cat | to_yaml) sample.yml输出a: | foo: cat baz: dog更新单行内嵌 YAML同样的表达式作用于单行字符串a: foo: baryq .a | (from_yaml | .foo cat | to_yaml) sample.yml输出a: foo: cat对比可见多行输入保持|块标量形态单行输入则保持单行引号形态。这正是 encodeOperator 中decoded:变量机制在起作用——decodeOperator先把原始候选节点存入context.SetVariable(decoded: candidate.GetKey(), ...)编码时再取出比对若原始值不是以换行结尾且编码结果恰为单行就剔除多余的末尾换行。Properties.properties 配置的互转编码为 props 字符串给定sample.ymla: cool: thing执行yq .b (.a | props) sample.yml输出a: cool: thing b: | cool thing解码 props 字符串给定sample.ymla: |- catsgreat dogscool as well执行yq .a | propsd sample.yml输出a: cats: great dogs: cool as well从 format.go 可见Properties 使用NewPropertiesEncoder与NewPropertiesDecoder配合 properties.go 中分隔符与多行值的解析逻辑。若想了解 Properties 在整文件层面的转换如yq -pprops -oyaml可参考 properties 使用文档。CSV 与 TSV标量数组、数组的数组与首行表头CSV 与 TSV 的编解码在源码中共用CSVFormat/TSVFormat编码器同为NewCsvEncoder只是偏好不同解码器同为NewCSVObjectDecoder。官方文档要求查阅 CSV/TSV 使用文档 了解其接受的输入形态要点如下编码支持两类输入同构扁平对象数组第一行对象包含全部 key、标量数组的数组scalars 指字符串、数字、布尔值解码假设第一行是表头其后每行成为对象数组中的一个元素表头作为 key。解码 CSV 字符串给定sample.ymla: |- cats,dogs great,cool as well执行yq .a | csvd sample.yml输出a: - cats: great dogs: cool as well解码 TSV 字符串TSV 只是把分隔符换成 Tab。给定a: |- cats dogs great cool as well执行yq .a | tsvd sample.yml输出a: - cats: great dogs: cool as well编码标量数组为 CSV给定- cat - thing1,thing2 - true - 3.40执行yq csv sample.yml输出cat,thing1,thing2,true,3.40注意元素thing1,thing2内含逗号被自动加引号包裹而布尔true、数字3.40保持原样——这得益于 CSV 编码器对字符串、数字、布尔值的类型感知。编码数组的数组为 CSV / TSV给定- - cat - thing1,thing2 - true - 3.40 - - dog - thing3 - false - 12执行yq csv sample.yml输出cat,thing1,thing2,true,3.40 dog,thing3,false,12执行yq tsv sample.yml输出字段以 Tab 分隔cat thing1,thing2 true 3.40 dog thing3 false 12csv与tsv同样是 0 缩进编码且由encodeOperator负责去除结尾换行因此适合直接重定向到.csv/.tsv文件。整文件级的-ocsv、-pcsv转换与表头行为细节可参考 csv-tsv 文档。XML属性前缀、内容名与缩进XML 与其他格式的关键差异在于XML 的属性和文本内容在 YAML 表示中需要约定标记。官方文档指出XML 使用--xml-attribute-prefix与--xml-content-name两个 flag 来识别属性字段与内容字段在 cmd/root.go 中可以看到它们分别绑定到ConfiguredXMLPreferences.AttributePrefix与ConfiguredXMLPreferences.ContentName默认属性前缀为内容名为content。编码为多行 XML 字符串给定sample.ymla: cool: foo: bar id: hi执行yq .a | to_xml sample.yml输出cool idhi foobar/foo /coolid键被识别为cool元素的属性渲染为idhi。编码为单行 XMLxmlyq .a | xml sample.yml输出cool idhifoobar/foo/coolxml与to_xml的差别同 JSON 一致前者固定 0 缩进后者默认 2 缩进。自定义缩进to_xml(1)yq {cat: .a | to_xml(1)} sample.yml输出cat: | cool idhi foobar/foo /cool解码 XML 字符串给定sample.ymla: foobar/foo执行yq .b (.a | from_xml) sample.yml输出a: foobar/foo b: foo: bar若你的 XML 使用自定义属性前缀如--xml-attribute-prefixattr或自定义内容字段名from_xml/to_xml会遵循同样的全局偏好保证编解码往返一致。更完整的 XML 处理命名空间、CDATA 等可参考 xml 使用文档。Base64RFC 4648 标准编码官方文档明确了两点约束Base64 采用 RFC 4648 使用 Go 标准库base64.StdEncoding并在Init阶段自动去除首尾空白、补齐填充padLen : len(stripped) % 4因此解码时即使输入缺少填充字符也能正确还原。编码字符串为 Base64给定sample.ymlcoolData: a special string执行yq .coolData | base64 sample.yml输出YSBzcGVjaWFsIHN0cmluZw编码整个 YAML 文档为 Base64先经yaml把对象结构转成字符串再交给base64yq yaml | base64 sample.yml给定a: apple输出YTogYXBwbGUK这是把 YAML 文档打包进另一个 YAML 字段的常用手法。解码 Base64 字符串解码结果假定为字符串。给定coolData: V29ya3Mgd2l0aCBVVEYtMTYg8JYig执行yq .coolData | base64d sample.yml输出Works with UTF-16 注意这里演示的是 UTF-16 内容被先转成 UTF-8 字节再编码解码后即为 UTF-8 的Works with UTF-16 。由于实现假定 UTF-8 文本直接对二进制文件内容做 base64 往返不在其保证范围内。解码并解析 Base64 中的 YAML管道串联base64d与from_yamlyq .coolData | (base64d | from_yaml) sample.yml给定coolData: YTogYXBwbGUK输出coolData: a: apple注意此处用的是|而非因为目标是原地替换coolData字段的值。这与 operator_load.go 提供的load_base64等文件加载运算符思路一致只是这里直接从字段值读取。URI百分号编码与解码URI 编码用于把字符串安全地放进 URL。给定coolData: this has special () characters *执行yq .coolData | uri sample.yml输出thishas%26special%28%29characters%2A注意空格被编码为表单风格、()、*被百分号编码。反向操作yq urid sample.yml对内容thishas%26special%28%29characters%2A解码输出this has special () characters *Shellsh 生成 Shell 友好字符串sh用于把字符串转成可直接放进sh/bash命令行的形式这在生成脚本、拼接 CI 命令时非常实用。给定coolData: strings with spaces and a quote执行yq .coolData | sh sample.yml输出strings with spaces and a \quote\其原理见 encoder_sh.gounsafeChars正则[^\w%:,./-]判定字符是否安全不安全的字符段用单引号块包裹遇到引号则退出单引号块 反斜杠转义 重新进入从而保证生成的字符串能在 shell 中安全使用。从 format.go 可以看到ShFormat只有EncoderFactory而没有DecoderFactory因此sh没有对应的解码运算符源码也提示非字符串节点会报错please first pipe through another encoding operator to convert the value to a string。实战组合与注意事项综合上述各格式可以把 encode/decode 家族归纳为三种典型用法嵌入Encode.field (.obj | to_json(0))、yaml | base64——把对象序列化后存进另一个 YAML 字段常用于配置模板、数据打包。解析Decode.a | csvd、.b (.a | from_xml)——把字符串化内容还原为可继续用 yq 表达式查询/修改的对象。往返更新Roundtrip.a | (from_yaml | .foo cat | to_yaml)——解码、修改、再编码并原地写回得益于decoded:变量机制单行与多行形态会被自动保留。实践中的几个关键点indent 参数只作用于可传参的三个编码函数to_yaml(i)、to_json(i)、to_xml(i)而yaml/json/xml速记分别固定为 2 / 0 / 0 缩进。csv、tsv、base64、uri、sh无缩进概念。JSON 解码后接style运算符因为 JSON 是 YAML 子集from_json会保留引号样式... style可得到地道的 YAML。CSV/TSV 解码默认以首行为表头且默认会对条目做 YAML/JSON 自动解析可用--csv-auto-parsef关闭见 csv-tsv 文档。XML 的属性与内容约定由--xml-attribute-prefix默认和--xml-content-name控制跨编解码时必须保持一致。Base64 面向 UTF-8 文本而非任意二进制且按 RFC 4648 标准实现自动处理空白与填充。这些运算符的完整行为均由仓库中的表格驱动测试覆盖operator_encoder_decoder_test.go官方文档 encode-decode.md 的每个示例都可直接复制运行验证。掌握这一族运算符后无论你面对的是嵌在 YAML 里的 JSON 配置、字符串化的 properties 文件还是需要 base64/URI 转义的动态内容都能用一条 yq 表达式完成解析与重组。【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。