# YAML 语法详细总结


# YAML 语法详细总结（基于 YAML 1.2 官方规范）
YAML 是 **YAML Ain't Markup Language** 的递归缩写，是一种人类优先、可读性极强的数据序列化格式，完全兼容 JSON 语法，广泛用于配置文件、数据交换、自动化编排等场景，主流稳定版本为 **YAML 1.2**（修复了1.1版本的诸多歧义问题）。

## 一、核心基础语法规则
这是YAML的语法基石，违反以下规则会直接导致解析失败。

### 1. 大小写敏感
YAML 对键名、值的大小写严格区分，`name` 和 `Name`、`port` 和 `Port` 是完全不同的两个键。
```yaml
Name: Alice  # 键1
name: Bob    # 键2，与上面互不影响
```

### 2. 缩进表示层级关系
YAML 完全依靠**空格缩进**定义数据层级，无大括号、中括号等强制包裹，核心规则：
- 绝对禁止使用 Tab 制表符缩进，必须使用纯空格；
- 缩进空格数不强制（推荐2个空格，云原生场景通用），**同一层级的元素必须保持完全一致的缩进**；
- 子层级的缩进必须比父层级多至少1个空格。
```yaml
# 正确示例
person:
  name: Tom
  age: 20
  address:
    city: Shanghai
    street: XX Road

# 错误示例（同级缩进不一致、Tab混用）
person:
name: Tom  # 缩进缺失
  age: 20
    address:  # 缩进层级错误
      city: Beijing
```

### 3. 键值对基础格式
YAML 核心结构是 `key: value` 键值对，强制规则：**冒号后面必须跟一个空格**，否则会被解析为一个完整的字符串键。
```yaml
# 正确
app: my-demo
version: 1.0.0

# 错误（冒号后无空格，解析失败）
app:my-demo
version:1.0.0
```

### 4. 注释规则
- 仅支持单行注释，使用 `#` 开头，`#` 后建议加空格提升可读性；
- 注释可放在行首，也可放在代码行的末尾；
- 无多行注释，多行注释需每行都加 `#`；
- 单引号/双引号内的 `#` 会被视为普通字符，不会解析为注释。
```yaml
# 这是全局注释
app_name: demo-app  # 这是行尾注释
# 多行注释
# 第二行注释
desc: "这是带#号的字符串，不会被注释"
```

### 5. 多文档分隔符
一个YAML文件中可包含多个独立的YAML文档，通过分隔符区分：
- `---`：表示一个文档的开始，单文档场景可省略，多文档必须用其分隔；
- `...`：表示一个文档的结束，非必需，仅用于明确终止文档，多用于网络传输场景。
```yaml
---
# 第一个文档：开发环境配置
env: dev
port: 8080
...
---
# 第二个文档：生产环境配置
env: prod
port: 80
```

## 二、核心数据类型
YAML 数据结构由三种核心类型组成：**标量（Scalar）**、**序列（Sequence）**、**映射（Mapping）**，支持无限嵌套组合。

### 1. 标量类型（单个不可拆分的值）
标量是YAML中最基础的数据单元，对应编程语言中的基础数据类型。

| 类型 | 规范说明 | 示例 |
| :--- | :--- | :--- |
| 字符串 | 最常用类型，支持无引号、单引号、双引号三种写法 | 见下方详细说明 |
| 整数 | 支持十进制、二进制（0b前缀）、八进制（0o前缀）、十六进制（0x前缀） | `num: 123` `hex: 0x1F` `bin: 0b1010` |
| 浮点数 | 支持小数、科学计数法 | `pi: 3.1415` `sci: 1.2e+5` |
| 布尔值 | 1.2规范仅支持 `true`/`false`（小写），废弃1.1的yes/no/on/off，避免歧义 | `is_enable: true` `is_delete: false` |
| 空值 | 支持 `null`、`~`、纯空三种写法，三者等价 | `empty1: null` `empty2: ~` `empty3: ` |
| 时间日期 | 遵循ISO 8601标准，自动解析为时间类型 | `date: 2026-04-16` `datetime: 2026-04-16T10:00:00+08:00` |

#### 字符串的三种写法与核心区别
字符串是YAML中最易踩坑的类型，三种写法有明确的语义差异：
1.  **无引号写法**：最简洁，适合纯文本、无特殊字符的字符串，自动识别类型；
    > 注意：包含 `:`+空格、`#`、`&`、`*`、`{}`、`[]` 等特殊字符时，不能用无引号写法，否则会被解析为语法结构。
    ```yaml
    # 正确
    desc: 这是一段普通的无引号字符串
    # 错误（:后有空格，会被解析为键值对）
    error_desc: 错误示例: 包含冒号加空格
    ```

2.  **单引号写法**：强字面量，内部的转义字符（如 `\n`）不会被解析，仅会把两个连续单引号转义为一个单引号，适合包含特殊字符、但不需要转义的场景。
    ```yaml
    # \n 会被当作普通字符，不会换行
    single_quote: '第一行\n第二行，不会换行'
    # 两个单引号转义为一个
    quote_test: '他说：''你好'''
    ```

3.  **双引号写法**：唯一支持转义字符的写法，内部的 `\n`、`\t` 等转义符会被正常解析，适合需要换行、特殊符号的复杂字符串。
    ```yaml
    # \n 会被解析为换行
    double_quote: "第一行\n第二行，正常换行"
    special_char: "包含双引号\"和转义字符的字符串"
    ```

### 2. 序列类型（数组/列表）
用于表示有序的一组数据，对应编程语言中的数组，支持两种写法：

#### 块式写法（推荐，可读性强）
以 `- `（短横线+空格）开头，每个元素占一行，同层级元素缩进一致，支持嵌套。
```yaml
# 基础序列
fruits:
  - Apple
  - Banana
  - Orange

# 嵌套序列（二维数组）
matrix:
  - [1, 2, 3]
  - [4, 5, 6]
  -
    - 7
    - 8
    - 9
```

#### 流式写法（行内写法）
用方括号 `[]` 包裹，元素之间用 `, `（逗号+空格）分隔，适合简短的列表。
```yaml
# 行内序列
nums: [1, 2, 3, 4, 5]
# 混合嵌套
person:
  name: Jack
  hobbies: [reading, running, coding]
```

### 3. 映射类型（字典/对象）
用于表示无序的键值对集合，对应编程语言中的字典/对象，支持两种写法：

#### 块式写法（推荐，可读性强）
每行一个键值对，通过缩进表示嵌套层级，是最常用的写法。
```yaml
# 基础映射
server:
  host: localhost
  port: 8080
  timeout: 30s

# 嵌套映射
user:
  name: Lucy
  age: 22
  contact:
    email: lucy@example.com
    phone: 138XXXX1234
```

#### 流式写法（行内写法）
用大括号 `{}` 包裹，键值对之间用 `, `（逗号+空格）分隔，适合简短的对象。
```yaml
# 行内映射
database: { driver: mysql, host: 127.0.0.1, port: 3306 }
# 混合嵌套
app:
  name: demo
  config: { env: dev, debug: true }
  white_list: [127.0.0.1, 192.168.1.1]
```

## 三、进阶高级语法
### 1. 多行字符串处理
YAML 提供了专门的符号处理多行文本，避免大量转义字符，核心分为两种模式：

#### 保留换行符 `|`（块字面量）
保留文本中所有的换行符和缩进，最终输出的文本会保留多行格式，适合脚本、配置文本、长文案等场景。
```yaml
# | 保留所有换行，末尾自动加一个换行
script: |
  #!/bin/bash
  echo "Hello YAML"
  cd /opt/app
  npm run start

# |+ 保留末尾所有换行（默认只保留1个，+ 保留全部）
text_plus: |+
  第一行
  第二行

# |- 删除末尾所有换行（默认的末尾换行也会删掉）
text_minus: |-
  第一行
  第二行
```

#### 折叠换行符 `>`（块折叠）
将文本中的换行符折叠为**一个空格**，最终输出为单行文本，仅保留空行对应的换行，适合超长的单行文案、说明文本。
```yaml
# > 把换行折叠为空格，最终输出为一行
summary: >
  这是一段超长的说明文本，
  我不想在一行里写满，
  用换行拆分，但最终解析后会合并为一行，
  换行符会变成空格。

# 空行会被保留为换行
desc: >



