Подтвердить что ты не робот

Как я могу выполнить конкатенацию строк или замену строк в YAML?

У меня есть это:

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

Как я могу использовать user_dir для user_pics? Если мне нужно указать другие свойства, подобные этому, это будет не очень СУХОЙ.

4b9b3361

Ответ 1

Вы можете использовать повторяющийся node, например:

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

Я не думаю, что вы можете конкатенировать, так что это не будет работать:

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

Ответ 2

Удивительно, поскольку цель якорей и ссылок YAML состоит в том, чтобы выделить дубликаты из файлов данных YAML, что нет встроенного способа объединения строк с использованием ссылок. Ваш пример использования построения пути по частям является хорошим примером - таких случаев должно быть много.

К счастью, есть простой способ добавить конкатенацию строк в YAML с помощью пользовательских тегов в 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]
""")

Что приводит к:

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

Вы можете добавить больше элементов в массив, например " " или "-", если строки должны быть разделены.

Ответ 3

Если вы используете python с PyYaml, объединение строк возможно в файле YAML. К сожалению, это только решение python, а не универсальное:

с os.path.join:

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

с string.join (для полноты - этот метод имеет гибкость, которую можно использовать для нескольких форм объединения строк:

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

Ответ 4

Я бы использовал массив, затем присоединил строку вместе с текущим символом разделителя OS

вот так:

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

Ответ 5

Мне кажется, что сам YAML не определяет способ сделать это.

Хорошая новость заключается в том, что потребитель YAML может понимать переменные.
Что будет использовать ваш YAML?

Ответ 6

string.join() не будет работать в Python3, но вы можете определить !join следующим образом:

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)