稍微重构了一下博客,因此学习一下这门语言

YAML 入门

YAML 概述

YAML 是一种用于数据序列化的轻量级语言,具有易读、易写的特点。它的名称 "YAML" 是 "YAML Ain't a Markup Language" 的递归缩写,这意味着 YAML 不是一种标记语言。然而,在最初的开发阶段,YAML 的全称其实是 "Yet Another Markup Language"(仍是一种标记语言),但随着其发展和使用,YAML 被重新定位为一种数据序列化格式,而非传统的标记语言。

YAML 的用途

YAML 被广泛用于配置文件和数据交换,特别是在需要人类可读性的场景下。它的语法简单直观,非常适合表示清单(列表)、散列表(键值对),以及标量(单一值)等复杂的数据结构。这使得 YAML 成为开发人员用来编写配置文件、数据输入输出、调试和文件大纲的理想选择。

YAML 的文件后缀

YAML 文件通常使用 .yaml.yml 作为文件扩展名。例如,config.ymlrunoob.yaml。两者在语法上没有任何区别,选择哪种取决于个人或项目的约定。

YAML 的应用领域

YAML 被广泛应用于各种领域,包括:

  • 配置文件: YAML 是许多应用程序和工具的配置文件格式,如 Docker、Ansible、Kubernetes、Travis CI 等。
  • 数据交换: YAML 可以用于系统之间的数据传输,特别是在 RESTful API 和微服务架构中。
  • 文档生成: YAML 常用于定义文档结构,如 Jekyll 博客引擎中的前置元数据。

示例: YAML 配置文件

以下是一个 YAML 配置文件的示例,它定义了一个简单的博客网站的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
site_name: My Awesome Blog
author: John Doe
email: john.doe@example.com

pages:
- title: Home
url: /
- title: About
url: /about/
- title: Blog
url: /blog/

database:
host: localhost
port: 3306
username: root
password: secret

features:
- comments
- search
- newsletter

接下来介绍一下语法:

基本语法

1. 大小写敏感

  • YAML 是大小写敏感的。这意味着 keyKey 是两个不同的键。

  • 例如:

    1
    2
    name: John
    Name: Doe

    在这个例子中,nameName 被视为两个不同的键。

2. 使用缩进表示层级关系

  • YAML 通过缩进来表示数据的层级结构。
  • 子元素相对于父元素需要缩进。
  • 缩进的层级代表数据的嵌套关系。

例如:

1
2
3
4
5
6
person:
name: John Doe
age: 30
address:
city: New York
country: USA

在这个例子中:

  • name, age, 和 addressperson 的子元素。
  • citycountryaddress 的子元素。

3. 缩进规则

  • 缩进不能使用 Tab 键,只能使用空格。
  • 缩进的空格数量可以是任意的,但相同层级的元素必须左对齐,即使用相同数量的空格。

例如:

1
2
3
4
5
6
7
correct_example:
first_level:
second_level: value

incorrect_example:
first_level:
second_level: value # 使用 Tab 键会导致错误

注意: 在不同层级之间,使用的空格数可以不同,但相同层级的元素必须对齐。

4. 注释

  • 使用 # 来表示注释,# 后面的内容将被忽略。
  • 注释可以放在单独一行,也可以放在数据行的后面。

例如:

1
2
3
# 这是一个注释
name: John Doe # 这是行尾注释
age: 30 # 用户的年龄

在这个例子中:

  • # 这是一个注释 是一行完整的注释。
  • # 这是行尾注释# 用户的年龄 是行尾注释。

5. 基本数据结构

  • 键值对(Mappings): 使用冒号(:)分隔键和值。

    例如:

    1
    2
    name: John Doe
    age: 30
  • 列表(Sequences): 使用连字符(-)表示列表项。

    例如:

    1
    2
    3
    4
    hobbies:
    - reading
    - swimming
    - coding
  • 字面量块(Block Scalars): 使用 |> 表示多行字符串,其中 | 保留换行符,> 折叠换行符。

    例如:

    1
    2
    3
    4
    5
    6
    7
    description: |
    这是一个多行字符串,
    会保留换行符。

    folded_text: >
    这是一个多行字符串,
    但换行符将被折叠为一个空格。

6. 文件后缀

  • YAML 文件通常以 .yaml.yml 作为文件后缀。
  • .yml.yaml 的缩写,两者没有任何区别,使用哪种取决于个人或项目的约定。

7. 特殊值

  • 布尔值: 可以使用 true / falseyes / no 来表示布尔值。
  • 空值: 可以使用 null~ 或者省略冒号后的值来表示空值。

例如:

1
2
3
4
is_admin: true
has_access: yes
not_set: null
empty_value:

8. 字符串表示

  • 字符串可以不加引号,但为了避免歧义,可以使用单引号(')或双引号(")。
  • 双引号支持转义字符,而单引号则不支持。

例如:

1
2
3
4
plain_string: Hello World
quoted_string: "Hello, World!"
escaped_string: "Hello, \"World\""
single_quoted: 'It''s a great day!'

9. 多文档语法

  • YAML 支持在同一个文件中包含多个文档,用 --- 分隔。
  • 每个文档可以包含独立的内容。

例如:

1
2
3
4
5
6
---
name: John Doe
age: 30
---
name: Jane Doe
age: 28

这表示两个独立的 YAML 文档。

数据类型

1. 对象(Objects)

对象是键值对的集合,也称为映射(mapping)、哈希(hashes)、或字典(dictionary)。对象在 YAML 中通常用于表示具有键值关系的数据结构,类似于 JSON 中的对象或 Python 中的字典。

表示方法:

  • 使用冒号 : 将键和值分开。
  • 每个键值对占一行,键和值之间用空格分隔。
  • 对象的键是唯一的,不能重复。

例子:

1
2
3
4
5
6
person:
name: John Doe
age: 30
address:
street: 1234 Elm Street
city: Springfield

解释:

  • person 是一个对象,包含多个键值对。
  • nameage 是简单的键值对。
  • address 是一个嵌套的对象,包含 streetcity 作为子键值对。

对象嵌套:

  • 对象可以嵌套,即一个对象的值可以是另一个对象。

1
2
3
4
5
company:
name: TechCorp
location:
city: New York
country: USA

在这个例子中,locationcompany 对象中的一个嵌套对象。

2. 数组(Arrays)

数组是一组按次序排列的值,也称为序列(sequence)或列表(list)。在 YAML 中,数组用于表示多个值的集合,这些值按照顺序排列,并且可以是任何类型的数据,包括对象、纯量或其他数组。

表示方法:

  • 使用连字符 - 表示数组中的每个元素。
  • 每个元素占一行,位于连字符后面,并且通常缩进两个空格。

例子:

1
2
3
4
fruits:
- Apple
- Banana
- Orange

解释:

  • fruits 是一个数组,包含三个元素:AppleBananaOrange
  • 数组中的每个元素都是一个纯量。

数组嵌套:

  • 数组可以包含其他数组或对象作为其元素。

1
2
3
4
5
6
7
8
9
10
11
employees:
- name: John Doe
age: 30
skills:
- Python
- JavaScript
- name: Jane Smith
age: 25
skills:
- Java
- C++

在这个例子中,employees 是一个数组,包含两个对象。每个对象有一个 skills 数组。

3. 纯量(Scalars)

纯量是单个的、不可再分的值,表示最基本的数据信息。在 YAML 中,纯量可以是字符串、数字、布尔值或空值等。

表示方法:

  • 纯量值可以直接写在键值对的冒号后面。
  • 字符串可以不加引号,但为了避免歧义或保留特殊字符,可以使用单引号 ' 或双引号 "

例子:

1
2
3
4
5
name: John Doe
age: 30
is_admin: true
description: "This is a description with special characters."
empty_value: null

解释:

  • name 是一个字符串类型的纯量。
  • age 是一个数字类型的纯量。
  • is_admin 是一个布尔类型的纯量,表示真值(true)。
  • description 是一个带双引号的字符串,保留了特殊字符。
  • empty_value 是一个空值(null),表示没有数据。

纯量的不同表示方法:

  • 多行字符串: 使用 |> 表示多行字符串,其中 | 保留换行符,> 折叠换行符。

    1
    2
    3
    4
    5
    6
    multiline_text: |
    This is a multi-line
    string in YAML.
    folded_text: >
    This string will be folded
    into a single line.

    解释:

    • multiline_text 使用 | 表示多行字符串,每一行的换行符都会保留。
    • folded_text 使用 > 表示折叠字符串,换行符将被转换为空格。
  • 对象 适用于表示键值对的结构化数据,是 YAML 中最常见的数据类型。
  • 数组 用于表示有序的数据列表,常用于需要表达多个值的场景。
  • 纯量 则用于表示单一的、不可再分的基本值,适合描述简单的数据元素。

引用

在 YAML 中,引用锚点&)、和别名*)是强大的功能,用于简化和优化配置文件的结构,减少重复内容。以下是对这些概念的详细解释。

1. 锚点 (&)

锚点用于创建一个可重用的内容块,赋予它一个名称(即锚点名)。锚点类似于为一段数据创建一个标签,之后可以在 YAML 文档的其他部分引用这段数据。

例子:

1
2
3
defaults: &defaults
adapter: postgres
host: localhost

解释:

  • &defaults 创建了一个锚点,名字为 defaults
  • 这个锚点包含了两个键值对:adapter: postgreshost: localhost

2. 别名 (*)

别名用于引用已经创建的锚点,并将锚点对应的内容插入到引用的位置。

例子:

1
2
3
development:
database: myapp_development
<<: *defaults

解释:

  • <<: *defaults 表示将 defaults 锚点的内容合并到 development 对象中。
  • *defaults 是一个别名,指向之前定义的 defaults 锚点。
  • 这意味着 development 中的内容将自动包含 defaults 锚点中定义的所有键值对。

3. 合并 (<<)

合并操作符 << 用于将锚点的内容与当前的数据结构合并。在上面的例子中,<<: *defaultsdefaults 锚点的内容合并到 development 对象中。

4. 综合例子

考虑以下 YAML 配置:

1
2
3
4
5
6
7
8
9
10
11
defaults: &defaults
adapter: postgres
host: localhost

development:
database: myapp_development
<<: *defaults

test:
database: myapp_test
<<: *defaults

解释:

  • defaults 锚点包含两个键值对:adapter: postgreshost: localhost
  • developmenttest 中,使用 <<: *defaults 引用并合并 defaults 的内容。
  • 因此,developmenttest 都将包含 adapter: postgreshost: localhost,而不需要重复这些内容。

5. 等价展开

上述 YAML 经过展开后,相当于以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
defaults:
adapter: postgres
host: localhost

development:
database: myapp_development
adapter: postgres
host: localhost

test:
database: myapp_test
adapter: postgres
host: localhost

解释:

  • developmenttest 中包含了 defaults 中的所有内容,并且在此基础上添加了各自的 database 键值对。

6. 列表中的引用

锚点和别名不仅可以在映射(对象)中使用,还可以在序列(列表)中使用。

例子:

1
2
3
4
5
- &showell Steve 
- Clark
- Brian
- Oren
- *showell

解释:

  • &showell Steve 创建了一个锚点 showell,其值为 Steve
  • 在列表的最后一项,使用 *showell 来引用这个锚点,因此最后一项的值也是 Steve

7. 等价展开

上面的 YAML 列表展开后等同于:

1
[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]

解释:

  • 列表中第一个和最后一个元素都是 Steve,因为最后一个元素是通过引用锚点 showell 得到的。
  • 锚点 (&) 用于创建一个可重用的内容块。
  • 别名 (*) 用于引用锚点,并将锚点的内容插入到当前位置。
  • 合并 (<<) 用于将锚点的内容合并到当前的数据结构中。

示例

以下是一个复杂的 YAML 配置文件示例,适用于一个假设的博客系统。这个例子展示了如何使用 YAML 来配置博客的多个方面,包括站点设置、页面配置、导航菜单、社交链接、文章分类、标签和插件设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# 博客基本设置
site:
name: My Awesome Blog
description: A place to share my thoughts and ideas.
url: https://www.myawesomeblog.com
author: Jane Doe
language: en

# 博客主题设置
theme:
name: sleek
color_scheme: dark
layout: two_columns
fonts:
body: 'Roboto, sans-serif'
headings: 'Lora, serif'
social_links:
github: https://github.com/janedoe
twitter: https://twitter.com/janedoe
linkedin: https://www.linkedin.com/in/janedoe/
logo: /assets/images/logo.png
favicon: /assets/images/favicon.ico

# 页面配置
pages:
home:
type: 'home'
layout: 'grid'
show_recent_posts: true
show_featured_posts: true

about:
type: 'static'
title: 'About Me'
content: >
Hi, I'm Jane Doe, a software engineer and blogger. This is my personal space on the internet where I share my thoughts on technology, programming, and life in general.

contact:
type: 'static'
title: 'Contact'
content: >
If you'd like to get in touch, please email me at [jane@example.com](mailto:jane@example.com).

# 导航菜单配置
menu:
- name: 'Home'
link: '/'
icon: 'home'

- name: 'About'
link: '/about'
icon: 'user'

- name: 'Blog'
link: '/blog'
icon: 'file-alt'

- name: 'Contact'
link: '/contact'
icon: 'envelope'

# 文章分类配置
categories:
- name: Technology
description: All about the latest in tech.
color: '#3498db'

- name: Programming
description: Tutorials, tips, and tricks about programming.
color: '#2ecc71'

- name: Life
description: Thoughts and stories about life.
color: '#e74c3c'

# 标签配置
tags:
- name: JavaScript
color: '#f39c12'

- name: Python
color: '#3498db'

- name: Web Development
color: '#2ecc71'

- name: Personal
color: '#e74c3c'

- name: Travel
color: '#9b59b6'

# 文章示例
posts:
- title: 'Getting Started with JavaScript'
date: 2024-01-01
author: Jane Doe
categories: ['Programming']
tags: ['JavaScript', 'Web Development']
content: >
JavaScript is one of the most popular programming languages in the world...

- title: 'My Trip to Japan'
date: 2024-02-15
author: Jane Doe
categories: ['Life']
tags: ['Travel', 'Personal']
content: >
Last month, I had the opportunity to visit Japan...

- title: 'Understanding Python Decorators'
date: 2024-03-10
author: Jane Doe
categories: ['Programming']
tags: ['Python']
content: >
Python decorators are a powerful tool...

# 插件配置
plugins:
analytics:
enabled: true
google_analytics_id: 'UA-XXXXXXXXX-X'

seo:
enabled: true
sitemap: true
robots: true

comments:
enabled: true
system: disqus
disqus_shortname: 'myawesomeblog'

# 自定义设置
custom:
show_subscribe_popup: true
show_author_bio: true
enable_dark_mode: true

# 其他设置
misc:
timezone: 'America/New_York'
date_format: 'YYYY-MM-DD'
time_format: 'HH:mm:ss'
default_category: 'Uncategorized'
show_related_posts: true

详细解释:

  1. 站点设置 (site): 配置博客的基本信息,如站点名称、描述、URL、作者姓名和语言。

  2. 主题设置 (theme): 定义博客的主题相关配置,如主题名称、配色方案、字体、社交链接、Logo 和 Favicon。

  3. 页面配置 (pages): 为博客的各个页面(如首页、关于页面、联系页面)配置具体内容和布局。

  4. 导航菜单配置 (menu): 设置博客的导航菜单,包括菜单项的名称、链接和图标。

  5. 文章分类配置 (categories): 定义博客文章的分类,每个分类都有一个名称、描述和颜色。

  6. 标签配置 (tags): 定义博客文章的标签,每个标签都有一个名称和颜色。

  7. 文章示例 (posts): 列出博客文章的示例,每篇文章包括标题、日期、作者、分类、标签和内容。

  8. 插件配置 (plugins): 配置博客使用的插件,如 Google Analytics、SEO 插件和评论系统。

  9. 自定义设置 (custom): 定义一些自定义的博客功能,如订阅弹窗、作者简介和暗模式支持。

  10. 其他设置 (misc): 其他杂项设置,如时区、日期格式、时间格式、默认分类和是否显示相关文章。

与其他结合

YAML 是一种数据序列化格式,本身并不包含逻辑或功能。它的作用是用于配置和数据交换,其主要目的是将数据以结构化的方式表示,以便其他语言(如 Python、JavaScript、Ruby 等)能够读取和使用这些数据。因此,要让 YAML 配置文件真正发挥作用,需要将它与编程语言或框架结合使用。

1. 与 Python 结合

在 Python 中,可以使用 PyYAML 库来解析和读取 YAML 文件,并将其内容转换为 Python 的数据结构(如字典、列表)。这些数据可以在应用程序中用作配置或参数。

示例:

1
2
3
4
5
6
7
8
import yaml

# 读取 YAML 文件
with open('config.yml', 'r') as file:
config = yaml.safe_load(file)

# 使用读取到的配置
print(config['site']['name']) # 输出: My Awesome Blog

2. 与 JavaScript 结合

在 Node.js 中,可以使用 js-yaml 库来解析 YAML 文件,将其转换为 JavaScript 对象。配置数据通常用于配置 Web 应用、构建工具或其他 JavaScript 项目。

示例:

1
2
3
4
5
6
7
8
9
10
const yaml = require('js-yaml');
const fs = require('fs');

// 读取 YAML 文件
try {
const config = yaml.load(fs.readFileSync('config.yml', 'utf8'));
console.log(config.site.name); // 输出: My Awesome Blog
} catch (e) {
console.log(e);
}

3. 与 Ruby on Rails 结合

在 Ruby on Rails 项目中,YAML 通常用作配置文件格式(如 database.yml)。Rails 提供了内置支持,可以自动加载并解析 YAML 文件,将其内容应用于数据库连接等配置。

示例:database.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
default: &default
adapter: postgresql
encoding: unicode
pool: 5
timeout: 5000

development:
<<: *default
database: myapp_development

test:
<<: *default
database: myapp_test

在 Ruby on Rails 中,这个文件将用于配置不同环境下的数据库连接信息。

4. 与 CI/CD 工具结合

在持续集成/持续交付(CI/CD)工具(如 GitLab CI、Travis CI)中,YAML 文件通常用来定义流水线的步骤。工具会读取 YAML 配置并执行相应的任务。

示例:.gitlab-ci.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
stages:
- build
- test
- deploy

build_job:
stage: build
script:
- echo "Compiling the code..."
- make

test_job:
stage: test
script:
- echo "Running tests..."
- make test

deploy_job:
stage: deploy
script:
- echo "Deploying to production..."
- make deploy

5. 与 Web 框架结合

在一些 Web 框架中,如 Jekyll 或 Hexo(静态网站生成器),YAML 文件通常用于前置数据(Front Matter)或全局配置。框架会读取这些 YAML 数据并根据配置生成 HTML 页面。

示例:Hexo 的 _config.yml

1
2
3
4
5
6
title: My Awesome Blog
subtitle: A place to share my thoughts and ideas.
author: Jane Doe
language: en
theme: sleek
url: https://www.myawesomeblog.com