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

如何用yq合并多个YAML文件并保留所有重复键值?

用yq合并YAML时合并重复键值(数组/逗号分隔字符串形式)

问题场景

现有三个YAML文件内容如下:

  • file1.yaml
A:
  a:
    a1: value1
  b: value2
B:
  b: value3
  • file2.yaml
A:
  a:
    a1: value2
  • file3.yaml
A:
  a:
    a1: value3

执行命令 yq ea '. as $item ireduce({}; . * $item)' file*.yaml 合并时,重复键A.a.a1仅保留最后一个值value3。需要将重复键的值合并为数组形式或逗号分隔的字符串,对应两种期望输出:

期望输出1(逗号分隔字符串)

A:
  a:
    a1: value1,value2,value3
  b: value2
B:
  b: value3

期望输出2(数组形式)

A:
  a:
    a1:
      - value1
      - value2
      - value3
  b: value2
B:
  b: value3

注:实际文件数量更多、结构更复杂,但值多为字符串,需支持值追加或新建键。


解决方案

方案1:合并为数组形式(对应期望输出2)

使用以下yq命令:

yq ea '
  . as $item ireduce({}; 
    reduce ($item | path(..)) as $path (.;
      if ($item | getpath($path)) | type == "string" then
        if getpath($path) | type == "string" then
          setpath($path; [getpath($path), $item | getpath($path)])
        elif getpath($path) | type == "array" then
          setpath($path; getpath($path) + [$item | getpath($path)])
        else
          setpath($path; [$item | getpath($path)])
        end
      else
        . * $item
      end
    )
  )' file*.yaml

如果需要去重,可在数组操作后添加| unique,比如[getpath($path), $item | getpath($path)] | unique。

逻辑说明:

  • 遍历每个文件的所有键路径
  • 针对字符串类型的值:
    • 目标路径无值:直接转为数组
    • 目标路径已有字符串:转为数组并加入新值
    • 目标路径已有数组:追加新值到数组
  • 非字符串类型的键值,保持*运算符的常规合并逻辑

方案2:合并为逗号分隔字符串(对应期望输出1)

基于字符串拼接逻辑实现:

yq ea '
  . as $item ireduce({}; 
    reduce ($item | path(..)) as $path (.;
      if ($item | getpath($path)) | type == "string" then
        setpath($path; (getpath($path) // "") + (if getpath($path) != "" then "," else "" end) + ($item | getpath($path)))
      else
        . * $item
      end
    )
  )' file*.yaml

逻辑说明:

  • 对字符串类型的重复键值,直接拼接为逗号分隔的字符串
  • // ""处理目标路径不存在的情况,避免空值报错
  • 非字符串类型的键值保持常规合并

内容的提问来源于stack exchange,提问作者Igor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:42:48