如何参考其"设定"从其他地方同其文件?
-
20-09-2019 - |
题
我有以下其:
paths:
patha: /path/to/root/a
pathb: /path/to/root/b
pathc: /path/to/root/c
我怎么可以"正常化"这一点,通过删除 /path/to/root/
从三个路径,并将它作为自己设置,是这样的:
paths:
root: /path/to/root/
patha: *root* + a
pathb: *root* + b
pathc: *root* + c
显然这是无效的,我只是做起来。什么是真正的语法?可以这样做?
解决方案
我不认为这是可能的。你可以重复使用“节点”,而不是它的一部分。
bill-to: &id001
given : Chris
family : Dumars
ship-to: *id001
这是完全有效的YAML和字段given
和family
在ship-to
块被重新使用。您可以重复标节点的方式相同,但有没有办法可以改变里面的内容和路径的那最后一部分从内部YAML添加到它。
如果重复打扰你这么多,我建议,让您的应用感知root
财产,并把它添加到每一个看起来相对不是绝对的。
其他提示
是,使用自定义标记。实施例在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
<强>某处thymeleaf 强>
<p th:utext='${@environment.getProperty("dir.default")}' />
<p th:utext='${@environment.getProperty("dir.proj1")}' />
<强>输出:强> /家庭/数据/中/ /家庭/数据/中/ P1
在某些语言中,可以使用替代的文库,例如, tampax 是的实施YAML处理变量:
const tampax = require('tampax');
const yamlString = `
dude:
name: Arthur
weapon:
favorite: Excalibur
useless: knife
sentence: "{{dude.name}} use {{weapon.favorite}}. The goal is {{goal}}."`;
const r = tampax.yamlParseString(yamlString, { goal: 'to kill Mordred' });
console.log(r.sentence);
// output : "Arthur use Excalibur. The goal is to kill Mordred."
我已经创建库,上Packagist可用,执行此功能: https://packagist.org/packages/grasmash/yaml-expander
实施例YAML文件:
type: book
book:
title: Dune
author: Frank Herbert
copyright: ${book.author} 1965
protaganist: ${characters.0.name}
media:
- hardcover
characters:
- name: Paul Atreides
occupation: Kwisatz Haderach
aliases:
- Usul
- Muad'Dib
- The Preacher
- name: Duncan Idaho
occupation: Swordmaster
summary: ${book.title} by ${book.author}
product-name: ${${type}.title}
实施例的逻辑:
// Parse a yaml string directly, expanding internal property references.
$yaml_string = file_get_contents("dune.yml");
$expanded = \Grasmash\YamlExpander\Expander::parse($yaml_string);
print_r($expanded);
合成阵列:
array (
'type' => 'book',
'book' =>
array (
'title' => 'Dune',
'author' => 'Frank Herbert',
'copyright' => 'Frank Herbert 1965',
'protaganist' => 'Paul Atreides',
'media' =>
array (
0 => 'hardcover',
),
),
'characters' =>
array (
0 =>
array (
'name' => 'Paul Atreides',
'occupation' => 'Kwisatz Haderach',
'aliases' =>
array (
0 => 'Usul',
1 => 'Muad\'Dib',
2 => 'The Preacher',
),
),
1 =>
array (
'name' => 'Duncan Idaho',
'occupation' => 'Swordmaster',
),
),
'summary' => 'Dune by Frank Herbert',
);
这是您的例子是无效的仅因为你选择了保留字符与开始你的标量。如果与其他一些非保留的字符替换*
(I倾向于使用非ASCII字符,只要是在很少使用的一些规范的一部分),则最终得到完全合法YAML:
paths:
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
这将加载到在你的解析器使用并不会奇迹般地展开任何语言映射的标准表示。结果 要做到这一点使用本地缺省对象类型,如以下Python程序:
# coding: utf-8
from __future__ import print_function
import ruamel.yaml as yaml
class Paths:
def __init__(self):
self.d = {}
def __repr__(self):
return repr(self.d).replace('ordereddict', 'Paths')
@staticmethod
def __yaml_in__(loader, data):
result = Paths()
loader.construct_mapping(data, result.d)
return result
@staticmethod
def __yaml_out__(dumper, self):
return dumper.represent_mapping('!Paths', self.d)
def __getitem__(self, key):
res = self.d[key]
return self.expand(res)
def expand(self, res):
try:
before, rest = res.split(u'♦', 1)
kw, rest = rest.split(u'♦ +', 1)
rest = rest.lstrip() # strip any spaces after "+"
# the lookup will throw the correct keyerror if kw is not found
# recursive call expand() on the tail if there are multiple
# parts to replace
return before + self.d[kw] + self.expand(rest)
except ValueError:
return res
yaml_str = """\
paths: !Paths
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
"""
loader = yaml.RoundTripLoader
loader.add_constructor('!Paths', Paths.__yaml_in__)
paths = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)['paths']
for k in ['root', 'pathc']:
print(u'{} -> {}'.format(k, paths[k]))
,它将打印:
root -> /path/to/root/
pathc -> /path/to/root/c
在膨胀是动态进行,并处理嵌套定义,但你必须要小心不能调用无限递归。
通过指定上述风挡,可以转储从在加载的数据中的原始YAML,因为上即时膨胀:
dumper = yaml.RoundTripDumper
dumper.add_representer(Paths, Paths.__yaml_out__)
print(yaml.dump(paths, Dumper=dumper, allow_unicode=True))
这将改变的映射键顺序。如果这是你有问题
使self.d
一个CommentedMap
(从ruamel.yaml.comments.py
进口)
我有写我自己的图书馆在Python扩大的变量正在从目录与一个层次结构,如:
/root
|
+- /proj1
|
+- config.yaml
|
+- /proj2
|
+- config.yaml
|
... and so on ...
关键的区别在于扩大适用必须只有在所有的 config.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/contools/contools/HEAD/tree/trunk/Scripts/Tools/cmdoplib.yaml.py https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools/cmdoplib.yaml.xsh
优点:
- 简单,不支持递归和嵌套变量
- 可以替换为一个未定义的变量占位(
${MYUNDEFINEDVAR}
->*$/{MYUNDEFINEDVAR}
) - 可以展开一个参考来自环境变量(
${env:MYVAR}
) - 可以替换所有的
\\
要/
在路径变量(${env:MYVAR:path}
)
弊:
- 不支持嵌套变量,因此不能扩大值中的嵌套的字典(喜欢的东西
${MYSCOPE.MYVAR}
不实现) - 没有检测到膨胀递归,包括递归后一个符把