友善且神奇的YAML 我们最近讲ansible提到了yaml,它是最近几年非常流行的一种,嗯,怎么说呢,本质是一种数据序列化的规范,使用上类似json、xml而又有所区别。

我们今天就来揭开YAML的神秘面纱。揭示其本质,与json、xml的异同,以及简单使用,为进一步编写ansible的playbook做准备。

什么是YAML YAML在介绍自己之前,先介绍自己不是什么,YAML就是 YAML Ain’t Markup Language (YAML™),它不是标记语言,而是a data serialization language designed to be human-friendly and work well with modern programming languages for common everyday tasks。它是一种数据序列化的语言,易于人读写,能很好的与当下的编程语言的一些任务相互协作。 ** 我们讲几个点**

它不是标记语言

标记语言是什么是一种将文本以及文本相关的其他信息结合起来,展现出关于文档结构和数据处理细节的电脑文字编码。与文本相关的其他信息(包括文本的结构和表示信息等)与原来的文本结合在一起,但是使用标记进行标识。比如html、xml以及时下流行的markdown,他们用plaintext里的文本对数据结构和文档结构处理,比如html中<h1>表示一级标题,<img>表示这是一个图片;markdown中用# 表示一级标题,[]表示图片等等。简单理解 肤浅理解,用一些规定好的规范将简单的字符富文本化。其中有一些xml等进行了扩展,实现了更高层面的东西。 ** 它是用于数据序列化**

这是本质,它是专职于数据序列化的语言,用于程序之间传递数据,将数据通过yaml承载,这点也是为什么人们经常将之与json、xml相提并论的原因。但是多多少少还是有点区别的,产生的原因,侧重的领域,使用的场景其实都是有细微差别的,一会我们简单讲讲。

它易于人的读写

我们见过xml也见过json、以及html,说实话,读写困难,层级有时候不易区分。但是YAML通过缩进和一些规范,使之读写都非常方便。

它可以很好的与当下的编程语言相互协作

官网对常用的语言都做出了对接的方式,作为各类语言内部或者之间一种数据序列化的标准设计,可以非常方便且无二义性的被各类语言识别,让数据的传递无差异,以便非常好的让程序处理我们的日常任务。这也是为什么ansible选择它来作为playbook的承载语言。

也因为以上原因,它被广泛运用在了配置文件、信息交换、对象持久化、数据检查等场景。它的文件后缀一般是.yml

YAML的使用 yaml的使用包括了两部分,一个是yaml数据的定义,一个是它在其他程序里如何被使用。

YAML 的基础语法 大小写敏感

使用缩进表示层级关系

不允许使用tab,只允许空格

缩进的空格数量不重要,只要层级相同的元素左对齐即可

‘#’ 表示注释,类似Python 注释生效到行末

YAML的数据结构 yaml 有三种基础的数据结构,

对象,key、value的键值对,可以称之为mapping、字典、哈希等等,约等于Python的dict,value可以是任何支持的数据结构。key值是字符串,按变量的要求命名,字幕开头不会有错的。

数组:一组按次序排列的值,value同样可以是任何支持的数据结构。类似于序列、列表。

纯量:单个不可再分的值,有点像Python中的基础数据结构,有字符串、布尔值、整数、浮点数、Null、时间、日期,这两个有别其他语言。

纯量中的字符串、数字我们比较熟了,我们分别为大家讲讲。

对象 对象的一组键值对,使用冒号结构表示。前面是key,后面是value。

device_name: fw01

类似Python中的

{‘device_name':’fw01‘}

对象可以是复合的,与数组、对象复合使用,表达复杂的数据。

对象与对象结合


# 对象中有对象
  dev_info:
    name: dev01
    auth_info:
      username: admin
      password: admin123
			

注意dev_info没有顶头写,也是可以的,但是不推荐。这里只是演示一下。

以下才是比较正规的写法


# 对象中有对象
dev_info:
  name: dev01
  auth_info:
  username: admin
  password: admin123
	
	

换行后根据情况对象这种,放两个空格表示层级比较合适。太少了层级个人觉得不明显,根据情况,有些比较复杂的可能放4个,看起来更舒服。数字没有严格的规范,个人觉得以看起来舒服为准的前提下不要太多。在vscode的yaml插件一般是用两个表示层级。

数组 以-开头,左对齐的1-N行构成一个数组


- dev01
- dev02
- dev03

以上等同于python中的[‘dev01’,’dev02’,’dev03’]

也可以在一行内写出数组成员

[dev01,dev02,dev03]

数组中的元素可以是对象,这样就类似于playbook中的一幕幕play了。


# this is a play list
- name: play 01 # 可以在-后空格后直接写kv,然后换行继续kv,kv的k值一定要对齐
  host: all

- # 可以换行写具体的对象值,playbook中这样写的少
  name: play 02
  host: huawei_devs
	

数组中的元素可以是数组


# 数组的数组
- 
  [dev1,dev2,dev3]

- 
  - 1
  - 2
  - 3

等同于

[['dev1', 'dev2', 'dev3'], [1, 2, 3]]

这个地方注意一下,1 2 3是数字。dev1-3是字符串,接下来我们就讲讲纯量。


**纯量**
我们赶时间,纯量你们一起上吧

# 常量的演示

# 整数 写成整数形式即可,也支持N进制表示
int:
    - 1
    - 0    #0
    - -2    #负数
    - 0b11_11 # 二进制,可以用_分割
    - 0x1a  # 16进制等等

float:
    - 1.2
    - 6.8523015e+5  #可以使用科学计数法

#  布尔值,true false 大小写多样
string:
    - it's a string
    - 'Hello world'  #可以使用双引号或者单引号包裹特殊字符
    - newline
      newline2    #字符串可以拆成多行,每一行会被转化成一个空格

boolean: 
    - TRUE  #true,True都可以
    - FALSE  #false,False都可以
# 浮点数,只要写成小数或者科学计数法就会被自动识别为浮点数
  
null:
    password: ~  #使用~表示null

date:
    - 2020-06-25    #日期必须使用ISO 8601格式,yyyy-MM-dd
datetime: 
    - 2020-06-25T15:08:31+08:00    #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区

以上用Python进行加载后如下


{'int': [1, 0, -2, 15, 26], 'float': [1.2, 685230.15], 'string': ["it's a string", 'Hello world', 'newline newline2'], 'boolean': [True, False], None: {'password': None}, 'date': [datetime.date(2020, 6, 25)], 'datetime': [datetime.datetime(2020, 6, 25, 7, 8, 31)]}

以上就是yaml的基本介绍,基于以上,我们应该足够可以看清楚

插一句 !!str 1 可以强制转换类型 1转成“1”

多yaml文档在一个文件中 在很多playbook中我们看到---开头,它用来在一个文件中区分多个yaml文档。

但是ansible都是用它来表示开始,ansible也讲究分而治之,会拆分yaml,没有遇到过去合并yaml,这个使用场景我暂时没遇到。


# this is a play list
---
- name: play 01
  host: all

- 
  name: play 02
  host: huawei_devs
---
- name: play 01
  host: all

- 
  name: play 02
  host: huawei_devs
	

用Python解析后是这样的

[{'name': 'play 01', 'host': 'all'}, {'name': 'play 02', 'host': 'huawei_devs'}][{'name': 'play 01', 'host': 'all'}, {'name': 'play 02', 'host': 'huawei_devs'}]

一会奉上代码。

与Json和xml的异同 这个简单讲讲吧,详细的大家可以看看官方文档的异同。

与json的区别: json目标是简单和一致,主要还是侧重数据序列化,在对人的读写方便,还是做的不够,yaml却做到了极致。

另外yaml还支持很多json不支持的一些特性比如锚点、类型转换等等。 ** 与XML的区别:** yaml和xml没半毛钱关系,仅仅是在一些领域使用(比如配置、比如数据承载)中二者可能偶遇被大家比较。他们有本质的区别,yaml是数据序列化的语言,xml是用来标记来描述文档的。

YAML的设计目标是:

The design goals for YAML are, in decreasing priority:

  1. YAML is easily readable by humans.
  2. YAML data is portable between programming languages.
  3. YAML matches the [native data structures](https://yaml.org/spec/1.2/spec.html#native data structure//) of agile languages.
  4. YAML has a consistent model to support generic tools.
  5. YAML supports one-pass processing.
  6. YAML is expressive and extensible.
  7. YAML is easy to implement and use. 某些方面和json与xml产生了使用上的交集、竞争仅此而已。他们各有侧重,yaml更侧重于human端,这是其他两种不具备的。

Python加载yaml文件 奉上一段Python解析yaml文件的代码

先安装pip install pyyaml


import yaml

def get_yaml_data(yaml_file):
    with open(yaml_file, 'r', encoding="utf-8") as f:
        yaml_data = f.read()

    data = yaml.load(yaml_data)
    print(data)
    
# 加载用---分割的多个yaml文档的文件
def get_multi_yaml_datas(yaml_file):
    with open(yaml_file, 'r', encoding="utf-8") as f:
        yaml_data = f.read()

    datas = yaml.load_all(yaml_data)
    for data in datas:
        print(data)
    
if __name__ == "__main__":
    get_multi_yaml_datas('example06.yml')
		

小结 以上就是我对yaml的讲解,下一节继续回归ansible,如果不出意外的话,顺祝大家端午节快乐!

欢迎点赞、在看、关注、收藏、分享等等~

参考:

https://yaml.org/spec/1.2/spec.html#id2803828

http://www.ruanyifeng.com/blog/2016/07/yaml.html

https://www.runoob.com/w3cnote/yaml-intro.html