首页 > 解决方案 > 将 YAML 文件与列表元素中的覆盖值合并

问题描述

我想合并两个包含列表元素的 YAML 文件。(A) 和 (B) 合并成一个新文件 (C)。

如果它们也在 (B) 中定义,我想覆盖 (A) 中列表条目的现有属性值。

如果未在 (A) 中定义但在 (B) 中定义,我想将新属性添加到列表条目中。

如果 (A) 中不存在,我还想添加 (B) 的新列表条目。

YAML 文件 A:

list:
  - id: 1
    name: "name-from-A"
  - id: 2
    name: "name-from-A"

YAML 文件 B:

list:
  - id: 1
    name: "name-from-B"
  - id: 2
    title: "title-from-B"
  - id: 3
    name: "name-from-B"
    title: "title-from-B"

合并后的 YAML 文件 (C),我想生成:

list:
  - id: 1
    name: "name-from-B"
  - id: 2
    name: "name-from-A"
    title: "title-from-B"
  - id: 3
    name: "name-from-B"
    title: "title-from-B"

我需要在 Bash 脚本中使用此功能,但我可以在环境中需要 Python。

是否有任何独立的 YAML 处理器(如 yq)可以做到这一点?

我将如何在 Python 脚本中实现这样的东西?

标签: pythonbashmergeyaml

解决方案


你可以使用ruamel.yamlpython 包来做到这一点。

如果您已经安装了 python,请在终端中运行以下命令:

pip install ruamel.yaml

改编这里的python代码。(经过测试,工作正常)

import ruamel.yaml
yaml = ruamel.yaml.YAML()

#Load the yaml files
with open('/test1.yaml') as fp:
    data = yaml.load(fp)
with open('/test2.yaml') as fp:
    data1 = yaml.load(fp)
# dict to contain merged ids
merged = dict()

#Add the 'list' from test1.yaml to test2.yaml 'list'
for i in data1['list']:
    for j in data['list']:
        # if same 'id'
        if i['id'] == j['id']:
            i.update(j)
            merged[i['id']] = True

# add new ids if there is some
for j in data['list']:
    if not merged.get(j['id'], False):
        data1['list'].append(j)

#create a new file with merged yaml
with open('/merged.yaml', 'w') as yaml_file:
    yaml.dump(data1, yaml_file)

推荐阅读