自动扩展YAML合并的工具?

jth*_*son 7 python yaml reformatting

我正在寻找一种可以轻松获取包含锚,别名和合并键的YAML文件并扩展别名并将其合并为平面YAML文件的工具或过程。仍然有许多不完全支持合并的常用YAML解析。

我希望能够利用合并使事情保持干燥的优势,但是在某些情况下,需要将其构建到更详细的“扁平” YAML文件中,以便其他依赖不完整工具的工具可以使用它YAML解析器。

源YAML示例:

default: &DEFAULT
  URL: website.com
  mode: production  
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600

development:
  <<: *DEFAULT
  URL: website.local
  mode: dev

test:
  <<: *DEFAULT
  URL: test.website.qa
  mode: test
Run Code Online (Sandbox Code Playgroud)

所需的输出YAML:

default:
  URL: website.com
  mode: production  
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600

development:
  URL: website.local
  mode: dev
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600

test:
  URL: test.website.qa
  mode: test
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600
Run Code Online (Sandbox Code Playgroud)

San*_*alp 7

我最近使用 yaml 进行了锚点的扩展

yq 'explode(.)' input.yaml > output.yaml
Run Code Online (Sandbox Code Playgroud)

这是使用golang yq


Ant*_*hon 5

如果您的系统上安装了python,则可以做pip install ruamel.yaml.cmd¹然后:

yaml merge-expand input.yaml output.yaml
Run Code Online (Sandbox Code Playgroud)

(替换output.yaml-写入标准输出)。这实现了合并扩展并保留了关键顺序和注释。

上面实际上是几行利用ruamel.yaml¹ 的代码,因此,如果您拥有Python(2.7或3.4+)并使用安装pip install ruamel.yaml并保存以下内容,则expand.py

import sys
from ruamel.yaml import YAML

yaml = YAML(typ='safe')
yaml.default_flow_style=False
with open(sys.argv[1]) as fp:
    data = yaml.load(fp)
with open(sys.argv[2], 'w') as fp:
    yaml.dump(data, fp)
Run Code Online (Sandbox Code Playgroud)

您已经可以:

python expand.py input.yaml output.yaml
Run Code Online (Sandbox Code Playgroud)

这将使您的YAML在语义上等同于您所请求的YAML(在output.yaml映射的键中排序,在此程序输出中不是)。

以上假设您的YAML中没有任何标签,也不在乎保留任何注释。通过使用标准YAML()实例的修补版本,可以保留其中大多数内容以及键顺序。修补是必需的,因为标准YAML()实例还保留了往返的合并,这正是您不想要的:

import sys
from ruamel.yaml import YAML, SafeConstructor

yaml = YAML()

yaml.Constructor.flatten_mapping = SafeConstructor.flatten_mapping
yaml.default_flow_style=False
yaml.allow_duplicate_keys = True
# comment out next line if you want "normal" anchors/aliases in your output
yaml.representer.ignore_aliases = lambda x: True  

with open(sys.argv[1]) as fp:
    data = yaml.load(fp)
with open(sys.argv[2], 'w') as fp:
    yaml.dump(data, fp)
Run Code Online (Sandbox Code Playgroud)

使用此输入:

default: &DEFAULT
  URL: website.com
  mode: production
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600  # an hour?

development:
  <<: *DEFAULT
  URL: website.local     # local web
  mode: dev

test:
  <<: *DEFAULT
  URL: test.website.qa
  mode: test
Run Code Online (Sandbox Code Playgroud)

这将给出此输出(请注意,对合并的键的注释会重复):

default:
  URL: website.com
  mode: production
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600  # an hour?

development:
  URL: website.local     # local web
  mode: dev

  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600  # an hour?

test:
  URL: test.website.qa
  mode: test
  site_name: Website
  some_setting: h2i8yiuhef
  some_other_setting: 3600  # an hour?
Run Code Online (Sandbox Code Playgroud)

以上是yaml merge-expand此答案开头提到的命令的作用。


¹ 免责声明:我是该软件包的作者。