YAML 语法

本页提供了正确 YAML 语法的基本概述,Ansible playbook(我们的配置管理语言)就是通过这种方式表达的。

我们使用 YAML 是因为相比于 XML 或 JSON 等其他常见的数据格式,它更易于人类阅读和编写。此外,大多数编程语言都有可用于处理 YAML 的库。

您可能还希望同时阅读 使用 playbook,以了解这在实践中是如何应用的。

YAML 基础

对于 Ansible,几乎每个 YAML 文件都以列表(list)开始。列表中的每个项目都是一组键/值对,通常被称为“哈希(hash)”或“字典(dictionary)”。因此,我们需要知道如何在 YAML 中编写列表和字典。

YAML 还有一个小特点。所有 YAML 文件(无论是否与 Ansible 相关)都可以选择以 --- 开始,并以 ... 结束。这是 YAML 格式的一部分,用于指示文档的开始和结束。

列表的所有成员都是处于同一缩进级别且以 "- "(一个短横线和一个空格)开头的行

---
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
...

字典以简单的 key: value 形式表示(冒号后必须跟一个空格)

# An employee record
martin:
  name: Martin D'vloper
  job: Developer
  skill: Elite

也可以实现更复杂的数据结构,例如字典列表、值是列表的字典,或两者的混合

# Employee records
- martin:
    name: Martin D'vloper
    job: Developer
    skills:
      - python
      - perl
      - pascal
- tabitha:
    name: Tabitha Bitumen
    job: Developer
    skills:
      - lisp
      - fortran
      - erlang

如果您确实需要,字典和列表也可以用简写形式表示

---
martin: {name: Martin D'vloper, job: Developer, skill: Elite}
fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']

这些被称为“流式集合(Flow collections)”。

Ansible 并不经常使用这些,但您还可以用几种不同的形式来指定 布尔值(true/false)

create_key: true
needs_agent: false
knows_oop: True
likes_emacs: TRUE
uses_cvs: false

如果您希望与默认的 yamllint 选项兼容,请在字典中使用小写的 ‘true’ 或 ‘false’ 作为布尔值。

值可以使用 |> 跨越多行。使用“字面量块标量(Literal Block Scalar)” | 跨行将保留换行符和任何尾随空格。使用“折叠块标量(Folded Block Scalar)” > 将把换行符折叠为空格;它用于使原本很长的行更易于阅读和编辑。在这两种情况下,缩进都将被忽略。示例见下文

include_newlines: |
            exactly as you see
            will appear these three
            lines of poetry

fold_newlines: >
            this is really a
            single line of text
            despite appearances

虽然在上面的 > 示例中所有换行都被折叠为空格,但有两种方法可以强制保留换行

fold_some_newlines: >
    a
    b

    c
    d
      e
    f

或者,可以通过包含换行符 \n 来强制实现

fold_same_newlines: "a b\nc d\n  e\nf\n"

让我们将目前学到的知识结合在一个任意的 YAML 示例中。这与 Ansible 实际上没有关系,但能让您对该格式有所感觉

---
# An employee record
name: Martin D'vloper
job: Developer
skill: Elite
employed: True
foods:
  - Apple
  - Orange
  - Strawberry
  - Mango
languages:
  perl: Elite
  python: Elite
  pascal: Lame
education: |
  4 GCSEs
  3 A-Levels
  BSc in the Internet of Things

这就是您在开始编写 Ansible playbook 之前真正需要了解的所有 YAML 知识。

注意事项

虽然您几乎可以将任何内容放入未加引号的标量中,但有一些例外。冒号后跟一个空格(或换行) ": " 是映射(mapping)的指示符。空格后跟井号 " #" 表示注释的开始。

正因为如此,以下内容将导致 YAML 语法错误

foo: somebody said I should put a colon here: so I did

windows_drive: c:

……但这样就可以工作

windows_path: c:\windows

如果哈希值中包含冒号且后面跟空格或处于行尾,您需要对该值加引号

foo: 'somebody said I should put a colon here: so I did'

windows_drive: 'c:'

……这样冒号就会被保留。

或者,您可以使用双引号

foo: "somebody said I should put a colon here: so I did"

windows_drive: "c:"

单引号和双引号的区别在于,在双引号中您可以使用转义字符

foo: "a \t TAB and a \n NEWLINE"

允许的转义列表可以在 YAML 规范的“Escape Sequences”(YAML 1.1)或“Escape Characters”(YAML 1.2)部分找到。

以下是无效的 YAML

foo: "an escaped \' single quote"

此外,Ansible 使用 “{{ var }}” 表示变量。如果冒号后的值以 “{” 开始,YAML 会认为它是一个字典,因此您必须对其加引号,如下所示

foo: "{{ variable }}"

如果您的值以引号开始,则整个值必须加引号,而不能仅对部分加引号。以下是一些关于如何正确加引号的额外示例

foo: "{{ variable }}/additional/string/literal"
foo2: "{{ variable }}\\backslashes\\are\\also\\special\\characters"
foo3: "even if it is just a string literal it must all be quoted"

非法变量名

foo: "E:\\path\\"rest\\of\\path

除了 '" 之外,还有许多特殊(或保留)字符不能用作未加引号标量的第一个字符: [] {} > | * & ! % # ` @ ,

您还应该注意 ? : -。在 YAML 中,如果后面跟着一个非空格字符,它们允许出现在字符串的开头,但不同的 YAML 处理器实现有所不同,因此最好使用引号。

在流式集合(Flow Collections)中,规则更为严格

a scalar in block mapping: this } is [ all , valid

flow mapping: { key: "you { should [ use , quotes here" }

布尔转换很有帮助,但当您需要字面量 yes 或其他布尔值作为字符串时,这可能会成为一个问题。在这种情况下,请直接使用引号

non_boolean: "yes"
other_string: "False"

YAML 会将某些字符串转换为浮点值,例如字符串 1.0。如果您需要指定版本号(例如在 requirements.yml 文件中),且该值看起来像浮点数,则需要对其加引号

version: "1.0"

另请参阅

使用 Playbook

了解 playbook 能做什么以及如何编写/运行它们。

YAMLLint

YAML Lint(在线版)可在您遇到问题时帮助您调试 YAML 语法

Wikipedia YAML 语法参考

一个优秀的 YAML 语法指南

YAML 1.1 规范

YAML 1.1 规范,PyYAML 和 libyaml 目前正在实现此版本

YAML 1.2 规范

为了完整性,YAML 1.2 是 1.1 的继任者

交流方式

有疑问?需要帮助?想分享你的想法?请访问 Ansible 通信指南