• 学好 Yaml


    简介

    之前是快速上手 yaml,这可以让我学习 kubernetes,但是真要工作用,总是差了一点东西,所以今天回炉重造。

    YAML 是一种较为人性化的数据序列化语言,可以配合目前大多数编程语言使用。

    YAML 的语法比较简洁直观,特点是使用空格来表达层次结构,其最大优势在于数据结构方面的表达,所以 YAML 更多应用于编写配置文件,其文件一般以 .yaml(或者 .yml) 为后缀。

    它的基本语法规则如下:

    • 大小写敏感
    • 使用缩进表示层级关系
    • 缩进时不允许使用Tab键,只允许使用空格
    • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
    • #表示注释,从这个字符一直到行尾,都会被解析器忽略。

    YAML 支持的数据结构有三种。

    对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
    数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
    纯量(scalars):单个的、不可再分的值
    
    • 1
    • 2
    • 3

    在一个文件中可以使用—表示文件开头…表示文件结尾,这样一个文件里等于同时保存多个文件了。


    学习工具

    学而不思则罔。

    pip install PyYaml
    
    • 1
    import yaml
    
    f = open("yaml.yaml")
    
    res = yaml.safe_load(f)
    
    print(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    对象

    使用key: value形式表示
    注意,冒号之后要加空格,否则无法解析

    father: dad
    Father: Dad
    
    • 1
    • 2

    {‘father’: ‘dad’, ‘Father’: ‘Dad’}

    这里由于大小写敏感,是两个对象

    支持多层嵌套(用缩进表示层级关系)

    father:
      child1: Jack
      child2: Bob
    
    • 1
    • 2
    • 3

    {‘father’: {‘child1’: ‘Jack’, ‘child2’: ‘Bob’}}

    支持**流式风格( Flow style)**的语法(用花括号包裹,用逗号加空格分隔,类似 JSON)

    father: {child1: Jack, child2: Bob}
    
    • 1

    {‘father’: {‘child1’: ‘Jack’, ‘child2’: ‘Bob’}}


    数组

    一组以区块格式(Block Format)(即“破折号+空格”)开头的数据组成一个数组

    animals:
      - Cat
      - Dog
      - Goldfish
    
    • 1
    • 2
    • 3
    • 4

    {‘animals’: [‘Cat’, ‘Dog’, ‘Goldfish’]}

    这里要和这种格式对比一下:

    animals:
    - Cat
    - Dog
    - Goldfish
    
    • 1
    • 2
    • 3
    • 4

    {‘animals’: [‘Cat’, ‘Dog’, ‘Goldfish’]}

    这俩是一个意思哈,第一次遇到的时候给我整懵了,我是认也不是,不认也不是。

    同时也支持内联格式(Inline Format)来表达(用方括号包裹,逗号加空格分隔,类似 JSON)

    values: [value1, value2, value3]
    
    • 1

    {‘values’: [‘value1’, ‘value2’, ‘value3’]}

    支持多维数组(用缩进表示层级关系)

    values:
      -
        - value1
        - value2
      -
        - value3
        - value4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    {‘values’: [[‘value1’, ‘value2’], [‘value3’, ‘value4’]]}

    注意,第2行和第5行不能添加东西,否则解析出来就不是二维数组了,如下面反例

    values:
      - sx1
        - value1
        - value2
      - sx2
        - value3
        - value4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    { values: [ ‘sx1 - value1 - value2’, ‘sx2 - value3 - value4’ ] }
    讲真,我不知道这东西在哪里用。

    好,我们继续做个辨析:

    values:
    -
    - value1
    - value2
    -
    - value3
    - value4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果是这样,{‘values’: [None, ‘value1’, ‘value2’, None, ‘value3’, ‘value4’]}

    values:
    -
    -   value1
    -   value2
    -
    -   value3
    -   value4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    跟上一个没差

    values:
    -
      - value1
      - value2
    -
      - value3
      - value4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个就是正常的二维数组了:{‘values’: [[‘value1’, ‘value2’], [‘value3’, ‘value4’]]}

    没啥特别的意思,如果是咱写代码,就写最开始那种标准的,别整这些花里胡哨的后来人看的都麻烦。


    纯量

    纯量是最基本的,不可再分的值,包括:

    字符串
    布尔值
    整数
    浮点数
    Null
    时间
    日期
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    下面是纯量的使用示例

    boolean: 
        - TRUE  #true,True都可以
        - FALSE  #false,False都可以
    float:
        - 3.14
        - 6.8523015e+5  #可以使用科学计数法
    int:
        - 123
        - 0b1010_0111_0100_1010_1110    #二进制表示
    null:
        nodeName: 'node'
        parent: ~  #使用~表示null
    string:
        - 哈哈
        - 'Hello world'  #可以使用双引号或者单引号包裹特殊字符
        - newline
          newline2       #字符串可以拆成多行,每一行会被转化成一个空格
    date:
        - 2018-02-17     #日期必须使用ISO 8601格式,即yyyy-MM-dd
    datetime: 
        -  2018-02-17T15:02:31+08:00    #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这里要特别注意一下这个字符串。

    JSON显示如下:

    {'boolean': [True, False], 'float': [3.14, 685230.15], 'int': [123, 685230], None: {'nodeName': 'node', 'parent': None}, 
    'string': ['哈哈', 'Hello world', 'newline newline2'], 'date': [datetime.date(2018, 2, 17)], 
    'datetime': [datetime.datetime(2018, 2, 17, 15, 2, 31, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))]}
    
    • 1
    • 2
    • 3

    字符串

    字符串是最常见,也是最复杂的一种数据类型。

    字符串一般不需要用引号包裹,但是如果字符串中使用了反斜杠“\”开头的转义字符就必须使用引号包裹

    strings:
      - Hello without quote        # 不用引号包裹
      - Hello
        world                      # 拆成多行后会自动在中间添加空格
      - 'Hello with single quotes' # 单引号包裹
      - "Hello with double quotes" # 双引号包裹
      - "I am fine. \u263A"        # 使用双引号包裹时支持 Unicode 编码
      - "\x0d\x0a is \r\n"         # 使用双引号包裹时还支持 Hex 编码
      - 'He said: "Hello!"'        # 单双引号支持嵌套"
      - \n \r             
      - '\n \r'                    
      - "\n \r"          
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    其JSON如下:

    {'strings': ['Hello without quote', 'Hello world', 'Hello with single quotes', 'Hello with double quotes', 'I am fine. ☺', '\r\n is \r\n', 'He said: "Hello!"', '\\n \\r', '\\n \\r', '\n \r']}
    
    • 1

    自己注意一下不同引号对结果的影响

    对于多行的文字,YAML 提供了两种特殊的语法支持

    保留换行(Newlines preserved)

    使用**竖线符“ | ”**来表示该语法,每行的缩进和行尾空白都会被去掉,而额外的缩进会被保留

    lines: |
      我是第一行
      我是第二行
        我是吴彦祖
          我是第四行
      我是第五行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    JSON格式如下:

    {‘lines’: ‘我是第一行\n我是第二行\n 我是吴彦祖\n 我是第四行\n我是第五行’}

    折叠换行(Newlines folded)

    使用**右尖括号“ > ”**来表示该语法,只有空白行才会被识别为换行,原来的换行符都会被转换成空格

    lines: >
      我是第一行
      我也是第一行
      我仍是第一行
      我依旧是第一行
    
      我是第二行
      这么巧我也是第二行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    其JSON格式如下:

    {‘lines’: ‘我是第一行 我也是第一行 我仍是第一行 我依旧是第一行\n我是第二行 这么巧我也是第二行’}

    注意,此方法最后一行末尾换行符会被识别

    还可以用+和-来选择是否保留文字块末尾的换行符

    s1: |
      Foo
    s2: |+
      Foo
    s3: |-
      Foo
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其JSON如下:

    {‘s1’: ‘Foo\n’, ‘s2’: ‘Foo\n’, ‘s3’: ‘Foo’}


    布尔值

    “true”、“True”、“TRUE”、“yes”、“Yes”和“YES”皆为真
    “false”、“False”、“FALSE”、“no”、“No”和“NO”皆为假

    boolean:
      - True
      - true
      - False
      - FALSE
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其JSON如下:

    {‘boolean’: [True, True, False, False]}


    整数

    支持二进制表示

    int:
      - 666    # 十进制
      - 0b10   # 0b 前缀,二进制
      - 010    # 0 前缀,八进制
      - 0x10   # 0x 前缀,十六进制
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其JSON如下:

    {‘int’: [666, 2, 8, 16]}


    浮点数

    支持科学计数法

    float:

    • 3.14
    • 6.8523015e+5
    • 6E3

    其JSON如下:

    {‘float’: [3.14, 685230.15, ‘6E3’]}

    指数必须是整数

    空值

    nulls:
      - 
      - null
      - Null
      - NULL
      - ~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其JSON如下:

    {‘nulls’: [None, None, None, None, None]}


    时间戳

    YAML 也支持 ISO 8601 格式的时间数据

    date1: 2020-05-20 13:14:00.820+08:00  # +8表示该时间就是东八区的时间
    date2: 2020-05-20 13:14:00.820  # 不加时区默认本初子母线的时间
    date3: 2020-05-20 13:14:00.820+8
    
    • 1
    • 2
    • 3

    其JSON显示为:

    {
    ‘date1’: datetime.datetime(2020, 5, 20, 13, 14, 0, 820000, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800))),
    ‘date2’: datetime.datetime(2020, 5, 20, 13, 14, 0, 820000),
    ‘date3’: datetime.datetime(2020, 5, 20, 13, 14, 0, 820000, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))
    }


    类型转换

    YAML 支持使用严格类型标签!!(双感叹号+目标类型)来强制转换类型,下面是内置类型

    !!int :整数类型
    !!float :浮点类型
    !!bool:布尔类型
    !!str:字符串类型
    !!binary:也是字符串类型
    !!timestamp :日期时间类型
    !!null:空值
    !!set:集合
    !!omap,!!pairs :键值列表或对象列表
    !!seq:序列,也是列表
    !!map:键值表
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    a: !!float '666' # !! 为严格类型标签
    b: '666' # 其实双引号也算是类型转换符
    c: !!str 666 # 整数转为字符串
    d: !!str 666.66 # 浮点数转为字符串
    e: !!str true # 布尔值转为字符串
    f: !!str yes # 布尔值转为字符串
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    数据重用与合并

    为了保持内容的简洁,避免过多重复的定义,YAML 提供了由锚点标签“&”和引用标签“*”组成的语法,利用这套语法可以快速引用相同的一些数据…

    a: &anchor # 设置锚点
      one: 1
      two: 2
      three: 3
    b: *anchor # 引用锚点
    
    • 1
    • 2
    • 3
    • 4
    • 5

    JSON:

    { a: { one: 1, two: 2, three: 3 },
    b: { one: 1, two: 2, three: 3 } }

    锚点必须加在冒号后,值之前,然后用*符号可以解引用

    配合合并标签“<<”使用可以与任意数据进行合并,你可以把这套操作想象成面向对象语言中的继承

    human: &base # 添加名为 base 的锚点
        body: 1
        hair: 999
    singer:
        <<: *base # 引用 base 锚点,实例化时会自动展开
        skill: sing # 添加额外的属性
    programer:
        <<: *base # 引用 base 锚点,实例化时会自动展开
        hair: 6 # 覆写 base 中的属性
        skill: code # 添加额外的属性
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其JSON如下:

    { human: { body: 1, hair: 999 },
    singer: { body: 1, hair: 999, skill: ‘sing’ },
    programer: { body: 1, hair: 6, skill: ‘code’ } }


    YAML语法的注意事项

    简单概括下几点在YAML型配置文件中需要注意的点:

    (1)使用空格进行缩进

    (2)用单引号包装正则表达式

    不是必须,但是最好使用单引号,解决YAML针对字符串转义的棘手规则。

    (3)用单引号包裹路径

    (4)避免在数值使用前导零

    如果09在数字字段中使用前盗铃(例如 ,)而不讲值包装在单引号中,则YAML解析器可能会错误地解析该值。

    要防止不需要的类型转换,请避免在字段值中使用前导零,或将值包装在单引号中。

  • 相关阅读:
    计算机存储文字码的底层实现和JAVA选择UTF-16存储char的原因
    mac电脑任务管理器 Things3 for Mac中文
    微调 TrOCR – 训练 TrOCR 识别弯曲文本
    Android环境配置笔记
    力扣 61. 旋转链表
    【Gensim概念】01/3 NLP玩转 word2vec
    C++【继承】
    Centos 7 安装 wget
    如何申请文心一言接口
    iPhone 如何强制重启
  • 原文地址:https://blog.csdn.net/qq_43762191/article/details/126901097