如何在YAML中进行字符串连接或字符串替换?

Geo*_*Geo 46 yaml concatenation

我有这个:

user_dir: /home/user
user_pics: /home/user/pics
Run Code Online (Sandbox Code Playgroud)

我如何使用user_dirfor user_pics?如果我必须指定这样的其他属性,它将不会非常干.

小智 42

您可以使用重复的节点,如下所示:

user_dir: &user_home /home/user
user_pics: *user_home
Run Code Online (Sandbox Code Playgroud)

我不认为你可以连接,所以这不会起作用:

user_dir: &user_home /home/user
user_pics: *user_home/pics
Run Code Online (Sandbox Code Playgroud)

  • 说实话 - 如果您不能使用这些指针来连接,我不明白这些指针的意义是什么..:/ (6认同)
  • 感谢您清理。我以为这是可能的,真是愚蠢。 (2认同)

Chr*_*son 31

令人惊讶的是,因为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]
""")
Run Code Online (Sandbox Code Playgroud)

结果如下:

{'user_dir': '/home/user', 'user_pics': '/home/user/pics'}
Run Code Online (Sandbox Code Playgroud)

您可以向数组添加更多项目,例如," "或者"-",如果字符串应该分隔.

  • 呃...那么,它与YAML有什么关系,YAML是一种独立于Python,Haskell或其他什么的标记语言? (7认同)
  • YAML规范说:"使用感叹号("!")使用标记表示显式类型...也可以使用特定于应用程序的本地标记." 我提供了符合规范的显式类型的实现.实施必须使用某种语言.我使用Python是因为OP说他想为他的YAML采用更"干"的方法,而DRY是Python人最常使用的术语.可以用其他语言实现相同的自定义标记.换句话说,OP提出的内容在vanilla YAML中不可用,但可以通过YAML定义的扩展机制获得. (4认同)
  • @Hi-Angel 正如 Chris Johnson 所说,这是 YAML 规范本身定义的显式扩展机制。而且没有必要刻薄。 (3认同)
  • @KenWilliams 好吧,我会记住这一点,所以下次我遇到使用 YAML 进行配置的专有应用程序时,如果我需要字符串连接,我应该要求作者为我提供解析器源代码和所有必要的构建系统件。 (2认同)
  • 现有答案*不会*修改 YAML 解析器代码。它并不假定您有权访问“yaml”包的源代码。它只是使用其公共 API 以 YAML 规范允许的方式对其进行扩展。 (2认同)

小智 9

如果您在PyYaml中使用python,则可以在YAML文件中连接字符串.不幸的是,这只是一个python解决方案,而不是普遍的解决方案:

os.path.join:

user_dir: &home /home/user
user_pics: !!python/object/apply:os.path.join [*home, pics]
Run Code Online (Sandbox Code Playgroud)

with string.join(为了完整起见 - 这种方法可以灵活地用于多种形式的字符串连接:

user_dir: &home /home/user
user_pics: !!python/object/apply:string.join [[*home, pics], /]
Run Code Online (Sandbox Code Playgroud)

  • 要清楚这种方法的含义-您允许Pyyaml解析器从yaml输入文件中执行任意Python代码。如果您不控制输入源,这将是一个非常危险的安全问题。许多程序将使用`yaml.safe_load()`函数来避免安全问题。在这种情况下,您的代码将无法工作。 (2认同)

小智 6

我会使用一个数组,然后将该字符串与当前的OS Separator符号连接在一起

像这样:

default: &default_path "you should not use paths in config"
pictures:
  - *default_path
  - pics
Run Code Online (Sandbox Code Playgroud)


Arn*_*psa 5

在我看来,YAML 本身没有定义执行此操作的方法

好消息是 YAML 使用者可能能够理解变量。
您的 YAML 将用于什么?