试图获取 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

注:

  1. 使用 --values 选项包括每个 YAML 路径的值。
  2. 出于兴趣,我更改了 --search 表达式以匹配输入文件中的 每个 节点,而不仅仅是“foo”数据。
  3. 默认输出(未设置--noescape)生成YAML路径,可用作其他YAML路径解析器和处理器的直接输入;设置 --noescape 将此更改为呈现人性化的路径,这可能无法用作下游 YAML 路径输入。

免责声明:我是yamlpath项目的作者。如果您 运行 遇到问题或对此有疑问,请访问项目的 GitHub 项目站点并通过问题(错误和功能请求)或讨论(问题)与我联系。谢谢!