我有以下YAML:

paths:
  patha: /path/to/root/a
  pathb: /path/to/root/b
  pathc: /path/to/root/c

我如何“正常化”它,通过从三个路径中删除/path/到/root/,并将其作为自己的设置,类似于:

paths:
  root: /path/to/root/
  patha: *root* + a
  pathb: *root* + b
  pathc: *root* + c

显然这是无效的,我瞎编的。真正的语法是什么?这能做到吗?


当前回答

使用Yglu,你可以这样写你的例子:

paths:
  root: /path/to/root/
  patha: !? .paths.root + a
  pathb: !? .paths.root + b
  pathc: !? .paths.root + c

声明:我是Yglu的作者。

其他回答

我用Python编写了自己的库来扩展从目录中加载的变量,其层次结构如下:

/root
 |
 +- /proj1
     |
     +- config.yaml
     |
     +- /proj2
         |
         +- config.yaml
         |
         ... and so on ...

这里的关键区别是,扩展必须在所有配置完成后才应用。Yaml文件被加载,其中来自下一个文件的变量可以覆盖来自前一个文件的变量,所以伪代码应该是这样的:

env = YamlEnv()
env.load('/root/proj1/config.yaml')
env.load('/root/proj1/proj2/config.yaml')
...
env.expand()

作为一个附加选项,xonsh脚本可以将结果变量导出到环境变量中(请参阅yaml_update_global_vars函数)。

脚本:

https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/cmdoplib/cmdoplib.yaml.xsh https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.yaml.py

优点:

简单,不支持递归和嵌套变量 可以将未定义的变量替换为占位符(${MYUNDEFINEDVAR} -> *$/{MYUNDEFINEDVAR}) 可以从环境变量(${env:MYVAR} ${env:MYVAR:path}可以替换所有的\\ to / in路径变量

缺点:

不支持嵌套变量,因此不能展开嵌套字典中的值(例如${MYSCOPE. xml)。MYVAR}未实现) 不检测展开递归,包括递归后的占位符放

是的,使用自定义标签。Python中的示例,使用!join标记连接数组中的字符串:

import yaml

## define custom tag handler
def join(loader, node):
    seq = loader.construct_sequence(node)
    return ''.join([str(i) for i in seq])

## register the tag handler
yaml.add_constructor('!join', join)

## using your sample data
yaml.load("""
paths:
    root: &BASE /path/to/root/
    patha: !join [*BASE, a]
    pathb: !join [*BASE, b]
    pathc: !join [*BASE, c]
""")

结果是:

{
    'paths': {
        'patha': '/path/to/root/a',
        'pathb': '/path/to/root/b',
        'pathc': '/path/to/root/c',
        'root': '/path/to/root/'
     }
}

join的参数数组可以包含任意数量的任何数据类型的元素,只要它们可以转换为字符串,因此!join [*a, "/", *b, "/", *c]就是您所期望的那样。

另一种方法是简单地使用另一个字段。

paths:
  root_path: &root
     val: /path/to/root/
  patha: &a
    root_path: *root
    rel_path: a
  pathb: &b
    root_path: *root
    rel_path: b
  pathc: &c
    root_path: *root
    rel_path: c

YML定义:

dir:
  default: /home/data/in/
  proj1: ${dir.default}p1
  proj2: ${dir.default}p2
  proj3: ${dir.default}p3 

在百里叶的某个地方

<p th:utext='${@environment.getProperty("dir.default")}' />
<p th:utext='${@environment.getProperty("dir.proj1")}' /> 

输出: / home /数据/ in / / home /数据/ in / p1

我认为这是不可能的。您可以重用“节点”,但不能重用它的一部分。

bill-to: &id001
    given  : Chris
    family : Dumars
ship-to: *id001

这是完全有效的YAML,并且给出的字段和家族在ship-to block中被重用。您可以以同样的方式重用标量节点,但您无法更改内部内容并从YAML中添加路径的最后一部分。

如果重复让你很困扰,我建议让你的应用程序意识到根属性,并将它添加到每个看起来相对而不是绝对的路径。