Frage

Ich habe folgendes YAML:

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

Wie kann ich „normalisieren“ dies durch /path/to/root/ von den drei Wegen zu entfernen, und hat es als seine eigene Einstellung, so etwas wie:

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

Ganz offensichtlich ist das ungültig, ich habe es einfach auf. Was ist die eigentliche Syntax? Es kann getan werden?

War es hilfreich?

Lösung

Ich glaube nicht, es ist möglich. Sie können „Knoten“, aber nicht Teil davon wiederverwenden.

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

Das ist absolut gültige YAML und Felder given und family in ship-to Block wiederverwendet werden. Sie können einen skalaren Knoten auf die gleiche Weise wieder verwenden, aber es gibt keine Möglichkeit, was drin ist, und fügen Sie den letzten Teil eines Weges, um es von innen YAML ändern können.

Wenn Wiederholung Sie sich die Mühe, dass viel schlage ich vor, die Anwendung bewusst root Eigentum zu machen, und fügen Sie ihn in jedem Pfad, sieht relativ nicht absolut.

Andere Tipps

Ja, mit benutzerdefinierten Tags. Beispiel in Python, nehmen Sie den !join Tag Herstellung Strings in einem Array:

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]
""")

Welche Ergebnisse in:

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

Das Array von Argumenten !join beliebige Anzahl von Elementen eines beliebigen Datentypen haben kann, solange sie in einem String umgewandelt werden können, so !join [*a, "/", *b, "/", *c] tut, was man erwarten würde.

Eine andere Möglichkeit, dies zu betrachten, ist einfach ein anderes Feld verwendet werden.

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 Definition:

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

Irgendwo in thymeleaf

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

Ausgang: / Home / data / in / / Home / data / in / p1

In einigen Sprachen können Sie eine alternative Bibliothek, zum Beispiel verwenden, tampax ist eine Implementierung von YAML Umgang mit Variablen:

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."

Ich erstelle habe eine Bibliothek, auf Packagist, dass führt diese Funktion aus: https://packagist.org/packages/grasmash/yaml-expander

Beispiel YAML-Datei:

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}

Beispiel Logik:

// 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);

Resultierende Array:

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',
);

Dass Ihr Beispiel ist ungültig nur , weil Sie ein reserviertes Zeichen wählen Sie Ihre Skalare zu beginnen. Wenn Sie die * mit einem anderen nicht-reservierten Zeichen ersetzen (neige ich dazu, nicht-ASCII-Zeichen zu verwenden, für die, wie sie selten als Teil einer Beschreibung verwendet werden), können Sie mit völlig legal YAML am Ende:

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

Dies wird in der Sprache Ihrer Parser verwendet für Zuordnungen in der Standarddarstellung laden und nicht auf magische Weise etwas erweitern.
dass für die Nutzung zu tun, um einen lokal Standardobjekttyp, wie im folgende Python-Programm:

# 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]))

, die gedruckt wird:

root -> /path/to/root/
pathc -> /path/to/root/c

Die Erweiterung on the fly und Griffe verschachtelt Definitionen durchgeführt wird, aber man muss vorsichtig sein, nicht eine unendliche Rekursion aufgerufen wird.

Durch die dumper angeben, können Sie die ursprüngliche YAML aus den Daten-Dump geladen in wegen der on-the-fly-Erweiterung:

dumper = yaml.RoundTripDumper
dumper.add_representer(Paths, Paths.__yaml_out__)
print(yaml.dump(paths, Dumper=dumper, allow_unicode=True))

das wird die Abbildungsschlüssel Bestellung ändern. Wenn das ein Problem ist, haben Sie man einen self.d (importiert aus CommentedMap)

ruamel.yaml.comments.py

Ich habe meine eigene Bibliothek auf Python geschrieben Variablen aus Verzeichnissen mit einer Hierarchie geladen erweitern werden wie:

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

Der wesentliche Unterschied ist, dass die Erweiterung nur Dateien nach allen den config.yaml angelegt werden muss, geladen wird, wobei die Variablen von der nächsten Datei, welche die Variablen aus dem vorherigen außer Kraft setzen können, so dass der Pseudo-Code soll wie folgt aussehen:

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

Als zusätzliche Option die xonsh Skript die resultierenden Variablen in Umgebungsvariablen exportieren kann (siehe yaml_update_global_vars-Funktion).

Die Skripte:

https: // Source .net / p / contools / contools / HEAD / Baum / trunk / Scripts / tools / cmdoplib.yaml.py https://sourceforge.net/ p / contools / contools / HEAD / Baum / trunk / Scripts / tools / cmdoplib.yaml.xsh

Pros :

  • einfach, unterstützt keine Rekursion und verschachtelte Variablen
  • kann eine undefinierte Variable auf einen Platzhalter ersetzen (${MYUNDEFINEDVAR} -> *$/{MYUNDEFINEDVAR})
  • kann eine Referenz von Umgebungsvariablen erweitern (${env:MYVAR})
  • kann alle \\ zu / in einer Pfadvariablen ersetzen (${env:MYVAR:path})

Cons :

  • unterstützt keine verschachtelten Variablen können so nicht erweitern Werte in verschachtelten Wörterbücher (so etwas wie ${MYSCOPE.MYVAR} ist nicht implementiert)
  • erkennt keine Expansion Rekursion, einschließlich Rekursion nach einem Platzhalter put
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top