목록 또는지도의 일부를 공유하기위한 YAML 구문이 있습니까?


95

그래서 나는 다음과 같이 할 수 있다는 것을 안다.

sitelist: &sites
  - www.foo.com
  - www.bar.com

anotherlist: *sites

그리고이 sitelistanotherlist모두 포함 www.foo.com하고 www.bar.com. 그러나, 내가 정말 원하는 것은입니다 anotherlist 포함 www.baz.com반복하지 않고, www.foo.com하고 www.baz.com.

이렇게하면 YAML 파서에서 구문 오류가 발생합니다.

sitelist: &sites
  - www.foo.com
  - www.bar.com

anotherlist: *sites
  - www.baz.com

앵커와 별칭을 사용하는 것만으로 다음과 같은 다른 수준의 하위 구조를 추가하지 않고는 원하는 작업을 수행 할 수 없습니다.

sitelist: &sites
  - www.foo.com
  - www.bar.com

anotherlist:
  - *sites
  - www.baz.com

즉,이 YAML 파일의 소비자는이를 알고 있어야합니다.

이와 같은 작업을 수행하는 순수한 YAML 방법이 있습니까? 아니면 변수 대체 구현이나 특정 유형의 하위 구조 자동 해제와 같은 YAML 이후 처리를 사용해야합니까? 나는 이미 몇 가지 다른 사용 사례를 처리하기 위해 그런 종류의 사후 처리를 수행하고 있으므로 완전히 싫어하지는 않습니다. 그러나 내 YAML 파일은 기계 생성이 아닌 사람이 작성하므로 표준 YAML 구문을 기반으로 사용자가 기억해야하는 규칙 수를 최소화하고 싶습니다.

또한지도로 비슷한 일을 할 수 있기를 바랍니다.

namedsites: &sites
  Foo: www.foo.com
  Bar: www.bar.com

moresites: *sites
  Baz: www.baz.com

YAML spec을 검색했는데 아무것도 찾을 수 없었기 때문에 대답은 "아니요 당신은 이것을 할 수 없습니다"라고 생각합니다. 그러나 누군가가 좋은 아이디어가 있다면.


편집하다: 대답이 없었기 때문에 아무도 내가 YAML 사양에없는 것을 발견하지 못했고 YAML 레이어에서 수행 할 수 없다고 가정하고 있습니다. 그래서 누군가가 나중에이 질문을 찾을 경우를 대비하여 YAML을 사후 처리하는 아이디어에 대한 질문을 열어 보겠습니다.


참고 : 이 문제는 YAML에서 앵커 및 별칭을 표준으로 사용하여 해결할 수도 있습니다. 참조 : YAML 배열을 병합하는 방법?
dreftymac

답변:


53

병합 키 유형 은 아마도 원하는 것입니다. <<병합을 나타 내기 위해 특수 매핑 키를 사용하여 매핑에 대한 별칭 (또는 이러한 별칭의 시퀀스)을 이니셜 라이저로 사용하여 단일 매핑으로 병합 할 수 있습니다. 또한 명시 적으로 값을 재정의하거나 병합 목록에없는 값을 더 추가 할 수 있습니다.

첫 번째 예로 시퀀스가 ​​아닌 매핑과 함께 작동한다는 점에 유의하는 것이 중요합니다. 이것은 당신이 그것에 대해 생각할 때 의미가 있으며, 당신의 예는 아마도 어쨌든 순차적 일 필요가없는 것처럼 보입니다. 시퀀스 값을 매핑 키로 변경하는 것만으로도 다음 (예상되지 않은) 예제와 같이 트릭을 수행 할 수 있습니다.

sitelist: &sites
  ? www.foo.com  # "www.foo.com" is the key, the value is null
  ? www.bar.com

anotherlist:
  << : *sites    # merge *sites into this mapping
  ? www.baz.com  # add extra stuff

주목할 몇 가지. 첫째, <<키이므로 노드 당 한 번만 지정할 수 있습니다. 둘째, 시퀀스를 값으로 사용할 때 순서가 중요합니다. 관련 값이 없기 때문에 여기의 예제에서는 중요하지 않지만 알아 두어야 할 가치가 있습니다.


아, 감사합니다! 꽤 도움이됩니다. 그래도 시퀀스에서는 작동하지 않습니다. 이 예에서는 순서가 중요하지 않다는 것이 맞습니다. 내가 가진 것은 개념적으로 세트이지만 매핑보다는 시퀀스에 훨씬 더 가깝게 매핑됩니다. 그리고 내가 얻은 것의 구조가 중요합니다 (이것이 구조를 병합하기 위해 다른 중첩 레이어를 추가하고 싶지 않은 이유입니다). 그래서 (모두 null) 값을 무시 해야하는 매핑을 갖는 것은 정말 작동하지 않습니다.
Ben

3
현재 공식 YAML 사양에는 아무것도 표시되지 않습니다 : yaml.org/spec/1.2/spec.html . 해당 페이지에는 "merge"라는 단어, "<<"텍스트, "key type"이라는 문구가 포함되어 있지 않습니다. << 구문은 Python yaml 패키지에서 작동합니다. 이러한 종류의 추가 기능에 대해 더 자세히 알아볼 수있는 곳을 알고 있습니까?
Ben

1
사양에 직접 포함되어 있지 않고 태그 저장소에 설명되어 있습니다. 기타 스키마 에는 일반적인 설명과 링크가 있습니다. 병합 키 외에도 세트 및 순서 세트가 있습니다. 그러나 YAML은 집합을 매핑 유형으로 간주합니다 (예 : 위의 예는 집합으로 구현 될 수 있음). 사용하는 언어로 결과 매핑에서 키를 값으로 바꿀 수 있습니까? 직접 구현해야하더라도 더 깨끗할 것이라고 생각합니다. 최소한 모든 데이터가 이미 그룹화되어 있고 YAML이 표준이 될 것입니다.
kittemon 2012 년

집합은 매핑이 아닙니다. 매핑은 키-값 연결의 집합입니다. 나는 때 yaml.load(...)파이썬에서, 나는 YAML 매핑의 표현으로 사전을 얻는다. 예,이를 세트로 사후 처리하는 것은 쉽지만, 그런 일이 발생했음을 알아야합니다 (그리고 규칙이 "세트는 널값이있는 맵으로 작성 됨"인 경우 구성 파일을 읽고 쓸 때 의미 론적 복잡성이 훨씬 높아집니다. ). 사이 난 후 처리가 필요 감안할 때 yaml.load(...)내가 사용 여부 결과 데이터를 사용 <<하거나 MERGE, 아마 고수 것이다 MERGE(나는 이미 지금 구현 한한다).

2
그래, 그게 효과가 있다는 걸 알았어 !!set. 하지만 너무 모호한 상용구입니다. 이 파일은 YAML 전문가가 아닌 사람들이 사람이 읽고 쓸 수 있도록 만들어졌습니다. 사람들은 사이트 목록을 YAML 목록으로 기록한 다음 병합하고 전체를 집합으로 변환해야하며 명시 적으로 집합으로 태그를 지정해야합니다. MERGE어쨌든 함께 일을 처리 합니다. 그래도 도와 ​​주셔서 감사합니다!

17

이전 답변에서 지적했듯이 YAML에서 목록을 확장하기위한 기본 제공 지원이 없습니다. 나는 그것을 직접 구현하는 또 다른 방법을 제공하고 있습니다. 이걸 고려하세요:

defaults: &defaults
  sites:
    - www.foo.com
    - www.bar.com

setup1:
  <<: *defaults
  sites+:
    - www.baz.com

이것은 다음으로 처리됩니다.

defaults:
  sites:
    - www.foo.com
    - www.bar.com

setup1:
  sites:
    - www.foo.com
    - www.bar.com
    - www.baz.com

아이디어는 '+'로 끝나는 키의 내용을 '+'가없는 해당 키에 병합하는 것입니다. 나는 이것을 Python으로 구현하고 여기에 게시 했습니다 .

즐겨!


2
참고 : 이 문제는 YAML에서 앵커 및 별칭을 표준으로 사용하여 해결할 수도 있습니다. 참조 : YAML 배열을 병합하는 방법?
dreftymac

12
이이 방법을 뜻에만 병합하는 별도의 도구로 작동 sites하고 sites+. 기본 yaml동작 이 아니기 때문에 사용자가 구현해야하는 도구를 의미 합니까?
stan0

7

(내가 사용하는 솔루션이 나중에 이것을 검색하는 모든 사람에게 유용한 경우 내 질문에 대답)

이 작업을 수행하는 순수한 YAML 방법이 없기 때문에 YAML 파서와 실제로 구성 파일을 사용하는 코드 사이에있는 "구문 변환"으로 구현할 것입니다. 따라서 내 핵심 애플리케이션은 인간 친화적 인 중복 방지 조치에 대해 전혀 걱정할 필요가 없으며 결과 구조에 직접 작용할 수 있습니다.

사용할 구조는 다음과 같습니다.

foo:
  MERGE:
    - - a
      - b
      - c
    - - 1
      - 2
      - 3

다음과 동일하게 변환됩니다.

foo:
  - a
  - b
  - c
  - 1
  - 2
  - 3

또는지도 사용 :

foo:
  MERGE:
    - fork: a
      spoon: b
      knife: c
    - cup: 1
      mug: 2
      glass: 3

다음으로 변환됩니다.

foo:
  fork: a
  spoon: b
  knife: c
  cup: 1
  mug: 2
  glass: 3

좀 더 공식적으로는 YAML 파서를 호출하여 구성 파일에서 네이티브 개체를 가져온 후 개체를 나머지 애플리케이션으로 전달하기 전에 애플리케이션에서 단일 키를 포함하는 매핑을 찾는 개체 그래프를 살펴 MERGE봅니다. 관련 값MERGE 은 목록 목록이거나 맵 목록이어야합니다. 다른 하위 구조는 오류입니다.

목록 목록의 경우 MERGE 표시된 순서대로 함께 연결된 하위 목록으로 대체됩니다.

맵 목록의 경우 포함 된 전체 맵 MERGE이 하위 맵의 모든 키 / 값 쌍을 포함하는 단일 맵으로 대체됩니다. 키에 겹치는 부분이있는 경우 하위 맵의 값은MERGE 목록 이 사용됩니다.

위에 제공된 예제는 원하는 구조를 직접 작성했을 수 있기 때문에 그다지 유용하지 않습니다. 다음과 같이 나타날 가능성이 더 높습니다.

foo:
  MERGE:
    - *salt
    - *pepper

노드에있는 모든 것을 포함 salt하고 pepper다른 곳에서 사용되는 목록이나 맵을 만들 수 있습니다 .

(나는 그 매핑에서 유일한 키 여야 foo:한다는 것을 보여주기 위해 외부지도를 계속 제공합니다. 즉 , 다른 최상위 이름이 없으면 최상위 이름으로 나타날 수 없습니다.)MERGEMERGE


6

여기 두 가지 답변에서 무엇인가를 명확히하기 위해 이것은 목록의 YAML에서 직접 지원되지 않습니다 (그러나 사전에는 지원됩니다. kittemon의 답변 참조).


참고 : 이 문제는 YAML에서 앵커 및 별칭을 표준으로 사용하여 해결할 수도 있습니다. 참조 : YAML 배열을 병합하는 방법?
dreftymac

5

Kittemon의 답변을 피기 백하려면 대체 구문을 사용하여 null 값으로 매핑을 만들 수 있습니다.

foo:
    << : myanchor
    bar:
    baz:

제안 된 구문 대신

foo:
    << : myanchor
    ? bar
    ? baz

Kittemon의 제안과 마찬가지로 매핑 내에서 앵커에 대한 참조를 사용하고 시퀀스 문제를 피할 수 있습니다. Symfony Yaml 구성 요소 v2.4.4가 ? bar구문을 다시 구성하지 않는다는 사실을 발견 한 후이 작업을 수행해야 합니다.


어떻게 myanchor생겼습니까?
ssc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.