Domanda

Ho il seguente YAML:

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

Come posso "normalizzare" questa, rimuovendo /path/to/root/ dai tre percorsi, e averlo come la propria impostazione, qualcosa come:

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

Ovviamente questo è valido, ho appena fatto in su. Qual è la sintassi reale? Può essere fatto?

È stato utile?

Soluzione

Non credo sia possibile. È possibile riutilizzare "nodo" ma non parte di esso.

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

Ciò è perfettamente valido e YAML campi given e family vengono riutilizzati nel blocco ship-to. È possibile riutilizzare un nodo scalare allo stesso modo, ma non c'è modo si può cambiare ciò che è dentro e aggiungere che l'ultima parte di un percorso ad esso dall'interno YAML.

Se la ripetizione si preoccupa più di tanto vi suggerisco di fare la vostra domanda a conoscenza della proprietà root e aggiungerlo ad ogni percorso che sembra relativa non assoluto.

Altri suggerimenti

Sì, utilizzando i tag personalizzati. Esempio in Python, rendendo il tag !join unire le stringhe in un 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]
""")

che si traduce in:

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

La matrice di argomenti per !join può avere qualsiasi numero di elementi di qualsiasi tipo di dati, purché possono essere convertiti in stringa, quindi !join [*a, "/", *b, "/", *c] fa quello che ci si aspetterebbe.

Un altro modo di guardare a questo è di usare semplicemente un altro campo.

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

definizione YML:

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

Da qualche parte in thymeleaf

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

Output: / Home / dati / in / / Home / dati / in / p1

In alcune lingue, è possibile utilizzare una libreria alternativa, ad esempio, Tampax è un'implementazione del variabili di gestione 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."

ho creato una libreria, disponibile su Packagist, che esegue questa funzione: https://packagist.org/packages/grasmash/yaml-expander

file

Esempio 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}

logica Esempio:

// 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 risultante:

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

che il vostro esempio è valido è solo perché si è scelto un carattere riservato per iniziare la vostra scalari con. Se si sostituisce il * con qualche altro carattere non riservato (Io tendo ad usare caratteri non-ASCII per questo in quanto sono raramente utilizzati come parte di una certa specifica), si finisce con YAML perfettamente legale:

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

Questo caricherà nella rappresentazione standard per mappature nella lingua tua parser utilizza e non magicamente espande nulla.
Per fare questo utilizzare un tipo di oggetto a livello locale di default come nel seguente programma 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]))

che stamperà:

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

L'espansione è fatto al volo e gestisce le definizioni annidate, ma bisogna stare attenti a non invocare ricorsione infinita.

Specificando il dumper, è possibile scaricare il YAML originale dai dati caricati in, a causa dell'espansione on-the-fly:

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

questo cambierà l'ordinamento chiave mappatura. Se questo è un problema che avete per fare un self.d CommentedMap (importato da ruamel.yaml.comments.py)

Ho scritto la mia libreria su Python per espandere le variabili di essere caricati da directory con una gerarchia simile:

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

La differenza fondamentale è che l'espansione deve essere applicato solo dopo che tutti i file config.yaml viene caricato, dove le variabili dal file successivo possono ignorare le variabili dal precedente, in modo che il pseudocodice dovrebbe essere simile a questo:

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

Come opzione aggiuntiva lo script xonsh può esportare le variabili risultanti in variabili d'ambiente (vedere la funzione yaml_update_global_vars).

Gli script:

https: // sourceforge .net / P / contools / contools / capo / albero / tronco / Scripts / Strumenti / cmdoplib.yaml.py https://sourceforge.net/ p / contools / contools / capo / albero / tronco / Scripts / Strumenti / cmdoplib.yaml.xsh

Pro :

  • semplice, non supporta la ricorsione e le variabili nidificate
  • può sostituire una variabile non definita per un segnaposto (${MYUNDEFINEDVAR} -> *$/{MYUNDEFINEDVAR})
  • può espandere un riferimento da variabile ambientale (${env:MYVAR})
  • può sostituire tutti \\ a / in una variabile percorso (${env:MYVAR:path})

Contro :

  • non supporta le variabili nidificate, in modo da non può espandersi valori nei dizionari nidificati (qualcosa come ${MYSCOPE.MYVAR} non è implementata)
  • non rileva la ricorsione di espansione, tra cui la ricorsione dopo un segnaposto messo
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top