如何使用yq按名称条件新增或替换YAML数组元素
解决方案
你之前使用的*+运算符是数组拼接逻辑,不会按指定字段做匹配去重,所以重复运行时会生成重复条目。以下方案针对mikefarah/yq v4(当前主流发行版)实现,可实现按name字段匹配更新services数组,存在对应名称则替换、不存在则新增,重复执行不会生成重复条目。
适配场景的命令
1. 单次合并单个补丁文件,输出到终端预览
yq eval-all ' select(fileIndex == 0) as $master | select(fileIndex == 1) | .services[] as $patch | $master | .services |= (map(select(.name != $patch.name)) + [$patch]) ' Master.yaml service2.yaml
2. 批量合并所有补丁文件,直接写入Master.yaml
如果需要一次性合并多个服务补丁(比如service2.yaml、service3.yaml等所有服务配置文件),直接更新Master.yaml:
yq eval-all ' . as $item ireduce (load("Master.yaml"); $item.services[] as $patch | .services |= (map(select(.name != $patch.name)) + [$patch]) ) ' service*.yaml -i Master.yaml
命令逻辑说明
- 核心逻辑是每次处理补丁服务条目时,先过滤掉Master中
name和当前补丁一致的旧条目,再把补丁条目加入数组末尾,天然避免重复 - 重复执行命令时,同名条目会被最新的补丁内容覆盖,不会新增重复项
- 支持补丁文件包含多个服务条目,会批量处理所有条目
效果验证
执行上述命令后,Master.yaml的内容将和你预期的输出完全一致:
services: - name: service1 url: https://service1.microservice.net - name: service2 url: https://service22.microservice.net - name: service3 url: https://service3.microservice.net
内容的提问来源于stack exchange,提问作者Sanjay Melinamani
相关产品推荐
相关产品推荐

