我正在解析YAML并将其分解为多个不同的YAML文件。我使用PyYAML的构造函数来实现它,但效果很差。
这是我项目的一部分,我需要根据我收到的yaml文件中的键值解析并拆分成多个不同的yaml文件。
我收到的yaml文件看起来像这样
testname: testname
testall:
test1:
name: name1
location: 0
test2:
name: name2
location: 2
test3:
name: name3
location: 0
test4:
name: name4
location: 2
...
locations:
- 0
- 2
- ...
我想解析它并按设备拆分如下:
# location0.yaml
testname:test
tests:
test1:
name:test1
location:0
test3:
name: test3
location: 0
# location2.yaml
testname:test
tests:
test2:
name:test2
location:0
test4:
name: test4
location: 0
如何解析上面的表格?
虽然您可以使用PyYAML执行此操作,但您必须将自己限制为YAML 1.1。对于这种读 - 修改 - 写,你应该使用ruamel.yaml
(免责声明:我是该包的作者)。这不仅支持YAML 1.2,它还会保留任何注释,标签和锚名称,以防它们出现在源代码中,并且如果需要,可以保留标量,文字和折叠样式等的引号。
另请注意,您的输出是无效的YAML,您不能将多行普通(即未引用)标量作为(块样式)映射的关键。你必须写:
"testname:test
tests":
但我认为你的意思是成为根级映射的两个键:
testname: test
tests:
假设你的输入是在input.yaml
:
testname: testname
testall:
test1:
name: name1 # this is just the first name
location: 0
test2:
name: "name2" # quotes added for demo purposes
location: 2
test3:
name: name3 # as this has the same location as name1
location: 0 # these should be together
test4:
name: name4 # and this one goes with name2
location: 2
locations:
- 0
- 2
你可以做:
import sys
from pathlib import Path
import ruamel.yaml
in_file = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=6, offset=4) # this matches your input
yaml.preserve_quotes = True
data = yaml.load(in_file)
for loc in data['locations']:
out_name = f'location{loc}.yaml'
tests = {}
d = ruamel.yaml.comments.CommentedMap(dict(testname="test", tests=tests))
d.yaml_set_start_comment(out_name)
testall = data['testall']
for test in testall:
if loc == testall[test]['location']:
tests[test] = testall[test]
tests[test]['location'] = 0
# since you set location to zero and this affects data, make sure to remove
# the items. This will prevent things from going wrong in case the
# locations sequence does have zero, but not as its first number
for key in tests:
del testall[key]
yaml.dump(d, Path(out_name))
给location0.yaml
:
# location0.yaml
testname: test
tests:
test1:
name: name1 # this is just the first name
location: 0
test3:
name: name3 # as this has the same location as name1
location: 0 # these should be together
和location2.yaml
:
# location2.yaml
testname: test
tests:
test2:
name: "name2" # quotes added for demo purposes
location: 0
test4:
name: name4 # and this one goes with name2
location: 0