web-dev-qa-db-ja.com

YAMLで文字列の連結または文字列の置換を行うにはどうすればよいですか?

私はこれを持っています:

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

user_dir for user_pics?このような他のプロパティを指定する必要がある場合、あまり乾燥していません。

43
Geo

次のように、繰り返しノードを使用できます。

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

しかし、連結できるとは思わないので、これはないでしょう動作します:

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

YAMLアンカーと参照の目的はYAMLデータファイルから重複を除外することであるため、参照を使用して文字列を連結する組み込みの方法がないことは驚くべきことです。パーツからパス名を作成するユースケースは良い例です。多くのそのような用途が必要です。

幸いなことに、Pythonのカスタムタグを介してYAMLに文字列連結を追加する簡単な方法があります。

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

文字列を区切る必要がある場合は、" ""-"などのアイテムを配列に追加できます。

29
Chris Johnson

PyYamlでpythonを使用している場合、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], /]
9
user2502636

配列を使用してから、現在のOS区切り記号と文字列を結合します

このような:

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

YAML自体 これを行う方法を定義しない のように思えます。

良いニュースは、YAMLコンシューマーが変数を理解できる可能性があることです。
YAMLは何を使用しますか?

3
Arnis Lapsa

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)
0
bryan

2019年8月現在

Chris ' ソリューションを機能させるには、実際に_Loader=yaml.Loader_をyaml.load()に追加する必要があります。最終的に、コードは次のようになります。

_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)
_

詳細については、 このGitHubの問題 を参照してください。

0
bmiselis