我感觉这是不可能的,但是我有一个YAML片段,如下所示:
.map_values: &my_map
a: 'D'
b: 'E'
a: 'F'
section:
stage: *my_map['b']
我希望stage
的值为E
。
在YAML中这可能吗?我已经尝试过几乎所有我能想到的替代品。
答案 0 :(得分:0)
由于映射中存在重复的键,因此不允许 在YAML 1.2中(至少应在YAML 1.1中引发警告),这是 不起作用,但是即使您纠正了该错误,也无法做到这一点 只是锚和别名。
YAML中唯一可用的替代之类的替代方法是"Merge Key Language-Independent Type"。这在YAML规范中间接引用,但并未包含在其中,但在大多数解析器中都可用。
唯一允许它执行的操作是使用一个或多个其他映射的键值对“更新”映射,如果该映射中尚不存在该键。为此,您可以使用特殊键<<
,该特殊键具有别名或别名列表。
YAML规范中没有指定指定的功能来取消引用特殊密钥。
有些系统使用的模板会生成YAML,但是在此处应用这些模板存在两个主要问题:
模板语言本身经常与YAML语法中的指示符冲突, 将模板设为无效的YAML
,即使可以将模板作为有效的YAML加载,并且提取了 更新模板的其他部分,您需要将输入解析两次(一次获取 值以更新模板,然后解析更新的模板)。有潜力 YAML的复杂性及其解析器的相对较慢的速度,这可能令人望而却步
您可以做的是创建一些标签(例如!lookup
),并让其构造函数解释该节点。
由于该节点必须再次是有效的YAML,因此您必须决定使用序列还是映射。
在这两种情况下,您都必须为值和键包含一些特殊的语法
(例如在合并中使用的<<
)。
在示例中,我省略了虚假的单引号,具体取决于 您真正的价值观,您当然会需要它们。
使用序列的示例:
.map_values: &my_map
a: D
b: E
c: F
section: !Lookup
- *my_map
- stage: <b>
使用映射的示例:
.map_values: &my_map
a: D
b: E
c: F
section: !Lookup
>>: *my_map
stage: <b>
都可以即时构建数据(即没有过去的数据)
加载处理您的数据结构所必需的)。例如。使用Python和
input.yaml
中的序列“样式”:
import sys
import ruamel.yaml
from pathlib import Path
input = Path('input.yaml')
yaml = ruamel.yaml.YAML(typ='safe')
yaml.default_flow_style = False
@yaml.register_class
class Lookup:
@classmethod
def from_yaml(cls, constructor, node):
"""
this expects a two entry sequence, in which the first is a mapping X, typically using
an alias
the second entry should be an mapping, for which the values which have the form <key>
are looked up in X
non-existing keys will throw an error during loading.
"""
X, res = constructor.construct_sequence(node, deep=True)
yield res
for key, value in res.items():
try:
if value.startswith('<') and value.endswith('>'):
res[key] = X[value[1:-1]]
except AttributeError:
pass
return res
data = yaml.load(input)
yaml.dump(data, sys.stdout)
给出:
.map_values:
a: D
b: E
c: F
section:
stage: E
有几件事要注意:
<...>
是任意的,您既不需要开头也不需要
结束标记。我建议您使用一些没有
在YAML中具有特殊含义,因此您无需引用值。您可以例如用一些
众所周知的unicode点,但是在编辑器中键入它们往往很麻烦。from_yaml
时,锚点尚未完全构建。所以X
是一个空字典
稍后会被填充。用yield
构造的过程执行两步过程:我们首先
将res
“按原样”返回给构造函数,然后稍后对其进行更新。的构造阶段
加载程序知道如何在获得生成器而不是“正常”值时自动进行处理。try
.. except
可以处理不是字符串的映射值(即数字,日期,布尔值)。由于代码是标准的YAML,因此上述代码应该可以以任何一种方式实现 YAML解析器,与语言无关。