试图获取 YAML 文件中的所有路径
Trying to get all paths in a YAML file
我有一个输入 YAML 文件 (test.yml),如下所示:
# sample set of lines
foo:
x: 12
y: hello world
ip_range['initial']: 1.2.3.4
ip_range[]: tba
array['first']: Cluster1
array2[]: bar
来源包含一些键的方括号(可能为空)。
我正在尝试获取文件中所有路径的逐行列表,理想情况下如:
foo.x: 12
foo.y: hello world
foo.ip_range['initial']: 1.2.3.4
foo.ip_range[]: tba
foo.array['first']: Cluster1
array2[]: bar
我使用了 yamlpaths 库和 yaml-paths
CLI,但无法获得所需的输出。试试这个:
yaml-paths -m -s =foo -K test.yml
输出:
foo.x
foo.y
foo.ip_range\[\'initial\'\]
foo.ip_range\[\]
foo.array\[\'first\'\]
每个路径都在一行中,但输出包含所有转义字符 (\)。修改调用以删除 -m 选项 ("expand matching parent nodes") 修复了该问题,但输出不是每行一条路径:
yaml-paths -s =foo -K test.yml
给出:
foo: {"x": 12, "y": "hello world", "ip_range['initial']": "1.2.3.4", "ip_range[]": "tba", "array['first']": "Cluster1"}
知道如何在没有转义字符的情况下为每个路径条目获取一行吗?请问ruamel模块有没有查询路径的功能?
您的 "paths" 只不过是
YAML 文档中的映射(可能还有序列)。
这可以通过递归函数从 YAML 加载的数据中简单地生成:
import sys
import ruamel.yaml
yaml_str = """\
# sample set of lines
foo:
x: 12
y: hello world
ip_range['initial']: 1.2.3.4
ip_range[]: tba
array['first']: Cluster1
array2[]: bar
"""
def pathify(d, p=None, paths=None, joinchar='.'):
if p is None:
paths = {}
pathify(d, "", paths, joinchar=joinchar)
return paths
pn = p
if p != "":
pn += '.'
if isinstance(d, dict):
for k in d:
v = d[k]
pathify(v, pn + k, paths, joinchar=joinchar)
elif isinstance(d, list):
for idx, e in enumerate(d):
pathify(e, pn + str(idx), paths, joinchar=joinchar)
else:
paths[p] = d
yaml = ruamel.yaml.YAML(typ='safe')
paths = pathify(yaml.load(yaml_str))
for p, v in paths.items():
print(f'{p} -> {v}')
给出:
foo.x -> 12
foo.y -> hello world
foo.ip_range['initial'] -> 1.2.3.4
foo.ip_range[] -> tba
foo.array['first'] -> Cluster1
array2[] -> bar
虽然 Anthon 的回答肯定会产生您想要的输出,但我认为您的问题具体是关于如何让 yaml-paths
命令产生所需的输出。我将解决 那个 原始问题。
从版本 3.5.0 开始,yamlpath 项目的 yaml-paths
命令支持 --noescape
选项,该选项从输出中删除转义符号。使用您的输入文件和新选项,您可能会发现此输出更符合您的喜好:
$ yaml-paths --nofile --expand --keynames --noescape --values --search='=~/.*/' test.yml
foo.x: 12
foo.y: hello world
foo.ip_range['initial']: 1.2.3.4
foo.ip_range[]: tba
foo.array['first']: Cluster1
array2[]: bar
注:
- 使用
--values
选项包括每个 YAML 路径的值。
- 出于兴趣,我更改了
--search
表达式以匹配输入文件中的 每个 节点,而不仅仅是“foo”数据。
- 默认输出(未设置
--noescape
)生成YAML路径,可用作其他YAML路径解析器和处理器的直接输入;设置 --noescape
将此更改为呈现人性化的路径,这可能无法用作下游 YAML 路径输入。
免责声明:我是yamlpath项目的作者。如果您 运行 遇到问题或对此有疑问,请访问项目的 GitHub 项目站点并通过问题(错误和功能请求)或讨论(问题)与我联系。谢谢!
我有一个输入 YAML 文件 (test.yml),如下所示:
# sample set of lines
foo:
x: 12
y: hello world
ip_range['initial']: 1.2.3.4
ip_range[]: tba
array['first']: Cluster1
array2[]: bar
来源包含一些键的方括号(可能为空)。
我正在尝试获取文件中所有路径的逐行列表,理想情况下如:
foo.x: 12
foo.y: hello world
foo.ip_range['initial']: 1.2.3.4
foo.ip_range[]: tba
foo.array['first']: Cluster1
array2[]: bar
我使用了 yamlpaths 库和 yaml-paths
CLI,但无法获得所需的输出。试试这个:
yaml-paths -m -s =foo -K test.yml
输出:
foo.x
foo.y
foo.ip_range\[\'initial\'\]
foo.ip_range\[\]
foo.array\[\'first\'\]
每个路径都在一行中,但输出包含所有转义字符 (\)。修改调用以删除 -m 选项 ("expand matching parent nodes") 修复了该问题,但输出不是每行一条路径:
yaml-paths -s =foo -K test.yml
给出:
foo: {"x": 12, "y": "hello world", "ip_range['initial']": "1.2.3.4", "ip_range[]": "tba", "array['first']": "Cluster1"}
知道如何在没有转义字符的情况下为每个路径条目获取一行吗?请问ruamel模块有没有查询路径的功能?
您的 "paths" 只不过是 YAML 文档中的映射(可能还有序列)。
这可以通过递归函数从 YAML 加载的数据中简单地生成:
import sys
import ruamel.yaml
yaml_str = """\
# sample set of lines
foo:
x: 12
y: hello world
ip_range['initial']: 1.2.3.4
ip_range[]: tba
array['first']: Cluster1
array2[]: bar
"""
def pathify(d, p=None, paths=None, joinchar='.'):
if p is None:
paths = {}
pathify(d, "", paths, joinchar=joinchar)
return paths
pn = p
if p != "":
pn += '.'
if isinstance(d, dict):
for k in d:
v = d[k]
pathify(v, pn + k, paths, joinchar=joinchar)
elif isinstance(d, list):
for idx, e in enumerate(d):
pathify(e, pn + str(idx), paths, joinchar=joinchar)
else:
paths[p] = d
yaml = ruamel.yaml.YAML(typ='safe')
paths = pathify(yaml.load(yaml_str))
for p, v in paths.items():
print(f'{p} -> {v}')
给出:
foo.x -> 12
foo.y -> hello world
foo.ip_range['initial'] -> 1.2.3.4
foo.ip_range[] -> tba
foo.array['first'] -> Cluster1
array2[] -> bar
虽然 Anthon 的回答肯定会产生您想要的输出,但我认为您的问题具体是关于如何让 yaml-paths
命令产生所需的输出。我将解决 那个 原始问题。
从版本 3.5.0 开始,yamlpath 项目的 yaml-paths
命令支持 --noescape
选项,该选项从输出中删除转义符号。使用您的输入文件和新选项,您可能会发现此输出更符合您的喜好:
$ yaml-paths --nofile --expand --keynames --noescape --values --search='=~/.*/' test.yml
foo.x: 12
foo.y: hello world
foo.ip_range['initial']: 1.2.3.4
foo.ip_range[]: tba
foo.array['first']: Cluster1
array2[]: bar
注:
- 使用
--values
选项包括每个 YAML 路径的值。 - 出于兴趣,我更改了
--search
表达式以匹配输入文件中的 每个 节点,而不仅仅是“foo”数据。 - 默认输出(未设置
--noescape
)生成YAML路径,可用作其他YAML路径解析器和处理器的直接输入;设置--noescape
将此更改为呈现人性化的路径,这可能无法用作下游 YAML 路径输入。
免责声明:我是yamlpath项目的作者。如果您 运行 遇到问题或对此有疑问,请访问项目的 GitHub 项目站点并通过问题(错误和功能请求)或讨论(问题)与我联系。谢谢!