web-dev-qa-db-fra.com

Comment puis-je faire la concaténation de chaînes ou le remplacement de chaînes en YAML?

J'ai ceci:

user_dir: /home/user
user_pics: /home/user/pics

Comment pourrais-je utiliser le user_dir pour user_pics? Si je dois spécifier d'autres propriétés comme celle-ci, ce ne serait pas très SEC.

43
Geo

Vous pouvez utiliser un nœud répété, comme ceci:

user_dir: &user_home /home/user
user_pics: *user_home

Je ne pense pas que vous puissiez concaténer, alors cela ne serait pas fonctionne:

user_dir: &user_home /home/user
user_pics: *user_home/pics
39
Brian Wells

Il est surprenant, car le but des ancres et références YAML est de factoriser la duplication des fichiers de données YAML, qu'il n'y a pas de méthode intégrée pour concaténer des chaînes à l'aide de références. Votre cas d'utilisation de la création d'un nom de chemin à partir de pièces est un bon exemple - il doit y avoir de nombreuses utilisations de ce type.

Heureusement, il existe un moyen simple d'ajouter la concaténation de chaînes à YAML via des balises personnalisées en Python.

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("""
user_dir: &DIR /home/user
user_pics: !join [*DIR, /pics]
""")

Ce qui se traduit par:

{'user_dir': '/home/user', 'user_pics': '/home/user/pics'}

Vous pouvez ajouter d'autres éléments au tableau, comme " " ou "-", si les chaînes doivent être délimitées.

29
Chris Johnson

Si vous utilisez python avec PyYaml, la jonction de chaînes est possible dans le fichier YAML. Malheureusement, ce n'est qu'une solution python, pas universelle):

avec os.path.join:

user_dir: &home /home/user
user_pics: !!python/object/apply:os.path.join [*home, pics]

avec string.join (par souci d'exhaustivité - cette méthode a la flexibilité d'être utilisée pour plusieurs formes de jonction de chaînes:

user_dir: &home /home/user
user_pics: !!python/object/apply:string.join [[*home, pics], /]
9
user2502636

Je voudrais utiliser un tableau, puis joindre la chaîne avec le symbole de séparation du système d'exploitation actuel

comme ça:

default: &default_path "you should not use paths in config"
pictures:
  - *default_path
  - pics
6
Adam

Il me semble que YAML lui-même ne définit pas la façon de le faire .

La bonne nouvelle est que le consommateur YAML pourrait comprendre les variables.
À quoi servira votre YAML?

3
Arnis Lapsa

string.join() ne fonctionnera pas en Python3, mais vous pouvez définir un !join comme ça:

import functools
import yaml

class StringConcatinator(yaml.YAMLObject):
    yaml_loader = yaml.SafeLoader
    yaml_tag = '!join'
    @classmethod
    def from_yaml(cls, loader, node):
        return functools.reduce(lambda a, b: a.value + b.value, node.value)

c=yaml.safe_load('''
user_dir: &user_dir /home/user
user_pics: !join [*user_dir, /pics]''')
print(c)
0
bryan

En août 2019 :

Pour que la solution Chris ' fonctionne, vous devez en fait ajouter Loader=yaml.Loader À yaml.load(). Finalement, le code ressemblerait à ceci:

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("""
user_dir: &DIR /home/user
user_pics: !join [*DIR, /pics]
""", Loader=yaml.Loader)

Voir ce problème GitHub pour plus de détails.

0
bmiselis