1

给定 master.yml ...

containers:
  - name: project-a
    items:
      - CCC
  - name: project-z
    items:
      - CCC
      - DDD

...和一个 update.yml ...

- name: project-z
  items:
    - CCC
    - EEE

...我想将它合并到正确的条目中。这将给出:

containers:
  - name: project-a
    items:
      - CCC
  - name: project-z
    items:
      - CCC
      - DDD
      - EEE

如果更新适用于以下 yq 4project-a

yq ea 'select(fileIndex==0) * {"containers":select(fileIndex==1)}' master.yml update.yml

但是,通过提供的project-z更新,它错误地替换了第一个数组条目(最终得到两个project-zs)。

4

2 回答 2

1

在深入了解手册之后,我有这个:

yq ea 'select(fi==1).0.name as $p | (select(fi==0).containers.[] | select(.name==$p)) = (select(fi==1) | .0 | . headComment="AUTO-UPDATED") |  select(fi==0)'  master.yml update.yml

project-z它通过首先搜索name匹配update.yml然后完全替换内容来替换而不是合并。

我知道根本原因是数据被格式化为一个列表,它应该是一个字典name是唯一的)。

这将很容易合并,并且将来也会更好!

containers:
  project-a:
    items:
      - CCC
  project-z:
    items:
      - CCC
      - DDD
      - EEE

于 2021-03-04T09:15:20.933 回答
1

这类似于另一个 stackoverflow 问题,其中 kev 有一个非常巧妙的解决方案(我认为)。

我已经在这里添加了他的解决方案到 yq 文档:https ://mikefarah.gitbook.io/yq/operators/multiply-merge#merge-arrays-of-objects-together-matching-on-a-key

在您的情况下,这仅在第二个文件与第一个文件的结构匹配时才有效(也就是说,它也有“容器”作为父级):

yq eval-all '
(
  ((.containers[] | {.name: .}) as $item ireduce ({}; . *+ $item )) as $uniqueMap
  | ( $uniqueMap  | to_entries | .[]) as $item ireduce([]; . + $item.value)
) as $mergedArray
| select(fi == 0) | .containers  = $mergedArray
` file.yaml file2.yaml
containers:
  - name: project-a
    items:
      - CCC
  - name: project-z
    items:
      - CCC
      - DDD
      - CCC
      - EEE

基本上,它的工作原理是根据名称减少为合并地图(正如您提到的,如果已经是这种情况,这会容易得多),然后将其转换回数组。

免责声明:我写了 yq

于 2021-12-05T01:43:11.257 回答