동일한 YAML 파일의 다른 곳에서 YAML "설정"을 참조하는 방법은 무엇입니까?
다음 YAML이 있습니다.
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
속성을 인식 하고 절대적이지 않은 상대 경로로 추가하는 것이 좋습니다 .
예, 맞춤 태그를 사용합니다. 인용에서 예제 !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 / data / in / / home / data / in / 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',
);
귀하의 예제가 유효하지 것은 단지 당신이 당신의 스칼라를 시작하는 예약 된 문자를 선택했기 때문에. 를 *
예약되지 않은 다른 문자로 바꾸면 (일부 사양의 일부로 거의 사용되지 않기 때문에 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 / 도구 /cmdoplib.yaml.xsh
장점 :
- 단순, 재귀 및 중첩 변수를 지원하지 않음
- 정의되지 않은 변수를 자리 표시 자로 바꿀 수 있습니다 (
${MYUNDEFINEDVAR}
->*$/{MYUNDEFINEDVAR}
). - 환경 변수 (
${env:MYVAR}
) 에서 참조를 확장 할 수 있습니다. - 경로 변수 ( ) 에서 모두
\\
를/
로 바꿀 수 있습니다.${env:MYVAR:path}
단점 :
- 중첩 된 변수를 지원하지 않으므로 중첩 된 사전의 값을 확장 할 수 없습니다 (같은
${MYSCOPE.MYVAR}
것이 구현되지 않음). - 자리 표시 자 삽입 후 재귀를 포함하여 확장 재귀를 감지하지 못함
'IT' 카테고리의 다른 글
행을 결합하는 부트 유효성 (행 범위) (0) | 2020.07.22 |
---|---|
로직을 추가 할 MVC (Laravel) (0) | 2020.07.22 |
Node.JS에서 서버 측 이미지 조작에 어떤 라이브러리를 가지고 있습니까? (0) | 2020.07.22 |
기본 키가 아닌 외래 키 (0) | 2020.07.22 |
IFS = $ '\ n'의 정확한 의미는 무엇입니까? (0) | 2020.07.22 |