You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用yq对YAML数组执行upsert更新插入操作

问题描述

现有如下hello.yaml文件内容:

foos:
  - foo: foo1
    bar: hello
  - foo: foo2
    bar: world

已知更新foo = "foo1"对应条目的bar字段,可执行如下命令:

yq '( .foos[] | select(.foo == "foo1") | .bar) |= "goodbye cruel"' hello.yaml

命令执行后输出正确的更新结果:

foos:
  - foo: foo1
    bar: goodbye cruel
  - foo: foo2
    bar: world

现在需要实现数组的upsert效果:无法提前确认匹配条目是否存在时,匹配到对应条目就更新字段,匹配不到就插入符合要求的新条目。例如操作foo = "foo3"时,自动输出追加新条目的结果:

foos:
  - foo: foo1
    bar: hello
  - foo: foo2
    bar: world
  - foo: foo3
    bar: goodbye cruel

核心疑问:yq是否原生支持这类数组upsert操作,还是必须预先判断目标键是否存在,再分开执行插入、更新两类命令?


解答

目前常用的Go版本yq(v4及以上)支持单条命令完成数组upsert,不需要额外在shell层做存在性判断,也不需要拆分更新、插入两条命令分别执行。

直接在yq表达式内完成分支判断即可,参考命令如下:

yq '
(any(.foos[]; .foo == "foo3")) as $exists |
if $exists then
  (.foos[] | select(.foo == "foo3") | .bar) = "goodbye cruel"
else
  .foos += {"foo": "foo3", "bar": "goodbye cruel"}
end
' hello.yaml

命令执行效果:

  • 传入已存在的foo值(比如foo1、foo2)时,会直接定位到对应条目更新bar字段,和原有更新命令的行为完全一致
  • 传入不存在的foo值(比如foo3)时,会自动把构造好的新条目追加到foos数组末尾,实现插入效果

如果需要精简写法,也可以用下面的短命令,逻辑完全一致:

yq '(.foos[] | select(.foo=="foo3") | .bar) = "goodbye cruel" | .foos += (any(.foos[]; .foo=="foo3") | not) as $need | if $need then {"foo":"foo3","bar":"goodbye cruel"} else empty end' hello.yaml

内容的提问来源于stack exchange,提问作者Jimmy The Dog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 17:12:32