其实也无需了解得太深入,但是至少你得知道一个 yaml 文件在 Ruby 里加载成 Hash,或者在 Python 里加载成字典以后会是什么样子。看例子学习是最好不过的了。
细节请参考:https://yaml.org/YAML_for_ruby.html(虽然是英文,但是图文并茂,看起来丝毫不会有障碍)。
基本语法
1、使用空白字符为文件缩进来表示结构;不过不能使用跳格字符 (TAB)。
2、注解由井字号( # )开始,可以出现在一行中的任何位置,而且范围只有一行(也就是一般所谓的单行注释)
3、每个清单成员以单行表示,并用短杠 + 空白( - )起始。或使用方括号( [ ] ),并用逗号 + 空白( , )分开成员。
4、每个散列表的成员用冒号 + 空白( : )分开键值和内容。或使用大括号( { } ),并用逗号 + 空白( , )分开。
5、散列表的键值可以用问号 ( ? ) 起始,用来明确的表示多个词汇组成的键值。
6、字符串平常并不使用引号,但必要的时候可以用双引号 ( " ) 或单引号 ( ' ) 框住。
7、使用双引号表示字符串时,可用倒斜线( \ )开始的转义字符(这跟 C 语言类似)表示特殊字符。
8、区块的字符串用缩进和修饰符(非必要)来和其他数据分隔,有保存新行(preserve)(使用符号 | )或折叠新行(flod)(使用符号 > )两种方式。
9、在单一文件中,可用连续三个连字号(---)区分多个文件。
10、另外,还有选择性的连续三个点号( ... )用来表示文件结尾。
11、重复的内容可使从参考标记星号 ( * ) 复制到锚点标记( & )。
12、指定格式可以使用两个惊叹号 ( !! ),后面接上名称。
13、文件中的单一文件可以使用指导指令,使用方法是百分比符号 ( % )。有两个指导指令在 YAML1.1 版中被定义:
% YAML 指导指令,用来识别文件的 YAML 版本。
% TAG 指导指令,被用在 URI 的前缀标记。这个方法在标记节点的类型时相当有用。
14、YAML 在使用逗号及冒号时,后面都必须接一个空白字符,所以可以在字符串或数值中自由加入分隔符号(例如:5,280 或 http://www.wikipedia.org)而不需要使用引号。
另外还有两个特殊符号在 YAML 中被保留,有可能在未来的版本被使用 --( @ )和( ` )。
快速转换(in Ruby)
# Ruby
require 'yaml'
puts YAML.load_file("test.yaml").inspect
# test.yaml
receipt: Oz-Ware Purchase Invoice
date: 2012-08-06
customer:
given: Dorothy
family: Gale
items:
- part_no: A4786
descrip: Water Bucket (Filled)
price: 1.47
quantity: 4
- part_no: E1628
descrip: High Heeled "Ruby" Slippers
size: 8
price: 133.7
quantity: 1
bill-to: &id001
street: |
123 Tornado Alley
Suite 16
city: East Centerville
state: KS
ship-to: *id001
specialDelivery: >
Follow the Yellow Brick
Road to the Emerald City.
Pay no attention to the
man behind the curtain.
# Hash
{"receipt"=>"Oz-Ware Purchase Invoice",
"date"=>#<Date: 2012-08-06 ((2456146j,0s,0n),+0s,2299161j)>,
"customer"=>{"given"=>"Dorothy", "family"=>"Gale"},
"items"=>
[{"part_no"=>"A4786",
"descrip"=>"Water Bucket (Filled)",
"price"=>1.47,
"quantity"=>4},
{"part_no"=>"E1628",
"descrip"=>"High Heeled \"Ruby\" Slippers",
"size"=>8,
"price"=>133.7,
"quantity"=>1}],
"bill-to"=>
{"street"=>"123 Tornado Alley\n" + "Suite 16\n",
"city"=>"East Centerville",
"state"=>"KS"},
"ship-to"=>
{"street"=>"123 Tornado Alley\n" + "Suite 16\n",
"city"=>"East Centerville",
"state"=>"KS"},
"specialDelivery"=>
"Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain."}
清单(数组或列表)
简单序列
# Yaml
- Casablanca
- North by Northwest
- Notorious
# Ruby
["Casablanca", "North by Northwest", "Notorious"]
简单内置序列
# Yaml
seq: [ a, b, c ]
# Ruby
{"seq"=>["a", "b", "c"]}
嵌套序列
# Yaml
-
- foo
- bar
- baz
# Ruby
[["foo", "bar", "baz"]]
混合序列
# Yaml
- apple
-
- foo
- bar
- x123
- banana
- carrot
# Ruby
["apple", ["foo", "bar", "x123"], "banana", "carrot"]
深度嵌套序列
# Yaml
-
-
- uno
- dos
# Ruby
[[["uno", "dos"]]]
散列表(哈希或字典)
简单映射
# Yaml
name: John Smith
age: 33
# Ruby
{"name"=>"John Smith", "age"=>33}
简单内置映射
# Yaml
hash: { name: Steve, foo: bar }
# Ruby
{"hash"=>{"name"=>"Steve", "foo"=>"bar"}}
映射内序列
# Yaml
foo: whatever
bar:
- uno
- dos
# Ruby
{"foo"=>"whatever", "bar"=>["uno", "dos"]}
嵌套映射
# Yaml
foo: whatever
bar:
fruit: apple
name: steve
sport: baseball
# Ruby
{"foo"=>"whatever", "bar"=>{"fruit"=>"apple", "name"=>"steve", "sport"=>"baseball"}}
混合映射
# Yaml
foo: whatever
bar:
-
fruit: apple
name: steve
sport: baseball
- more
-
python: rocks
perl: papers
ruby: scissorses
# Ruby
{"foo"=>"whatever", "bar"=>[{"fruit"=>"apple", "name"=>"steve", "sport"=>"baseball"},
"more", {"python"=>"rocks", "perl"=>"papers", "ruby"=>"scissorses"}]}
序列内的映射
# Yaml
- work on YAML.py:
- work on Store
# Ruby
[{"work on YAML.py"=>["work on Store"]}]
映射内的序列
# Yaml
allow:
- 'localhost'
- '%.sourceforge.net'
- '%.freepan.org'
# Ruby
{"allow"=>["localhost", "%.sourceforge.net", "%.freepan.org"]}
键值合并
# Yaml
mapping:
name: Joe
job: Accountant
<<:
age: 38
# Ruby
{"mapping"=>{"name"=>"Joe", "job"=>"Accountant", "age"=>38}}
多行内置
# Yaml
languages: [ Ruby,
Perl,
Python ]
websites: { YAML: yaml.org,
Ruby: ruby-lang.org,
Python: python.org,
Perl: use.perl.org }
# Ruby
{"languages"=>["Ruby", "Perl", "Python"], "websites"=>{"YAML"=>"yaml.org",
"Ruby"=>"ruby-lang.org", "Python"=>"python.org", "Perl"=>"use.perl.org"}}
基本类型
字符串
# Yaml
--- String
# Ruby
"String"
字符串字符
# Yaml
- What's Yaml?
- It's for writing data structures in plain text.
- And?
- And what? That's not good enough for you?
- No, I mean, "And what about Yaml?"
- Oh, oh yeah. Uh.. Yaml for Ruby.
# Ruby
["What's Yaml?", "It's for writing data structures in plain text.", "And?", "And
what? That's not good enough for you?", "No, I mean, \"And what about Yaml?\"", "Oh,
oh yeah. Uh.. Yaml for Ruby."]
指标字符串
# Yaml
the colon followed by space is an indicator: but is a string:right here
same for the pound sign: here we have it#in a string
the comma can, honestly, be used in most cases: [ but not in, inline collections ]
# Ruby
{"the colon followed by space is an indicator"=>"but is a string:right here",
"same for the pound sign"=>"here we have it#in a string",
"the comma can, honestly, be used in most cases"=>["but not in", "inline collections"]}
强制转换字符串
# Yaml
date string: !str 2001-08-01
number string: !str 192
# Ruby
{"date string"=>"2001-08-01", "number string"=>"192"}
单引号字符串
# Yaml
all my favorite symbols: '#:!/%.)'
a few i hate: '&(*'
why do i hate them?: 'it''s very hard to explain'
# Ruby
{"all my favorite symbols"=>"#:!/%.)",
"a few i hate"=>"&(*",
"why do i hate them?"=>"it's very hard to explain"}
双引号字符串
# Yaml
i know where i want my line breaks: "one here\nand another here\n"
# Ruby
{"i know where i want my line breaks"=>"one here\nand another here\n"}
多行引号字符串
# Yaml
i want a long string: "so i'm going to
let it go on and on to other lines
until i end it with a quote."
# Ruby
{"i want a long string"=>"so i'm going to let it go on and on to other lines until i end it with a quote."}
空值
# Yaml
name: Mr. Show
hosted by: Bob and David
date of next season: ~
# Ruby
{"name"=>"Mr. Show", "hosted by"=>"Bob and David", "date of next season"=>nil}
布尔
# Yaml
Is Gus a Liar?: true
Do I rely on Gus for Sustenance?: false
# Ruby
{"Is Gus a Liar?"=>true, "Do I rely on Gus for Sustenance?"=>false}
整型
# Yaml
zero: 0
simple: 12
one-thousand: 1,000
negative one-thousand: -1,000
# Ruby
{"zero"=>0, "simple"=>12, "one-thousand"=>1000, "negative one-thousand"=>-1000}
整型键
# Yaml
1: one
2: two
3: three
# Ruby
{1=>"one", 2=>"two", 3=>"three"}
浮点
# Yaml
a simple float: 2.00
larger float: 1,000.09
scientific notation: 1.00009e+3
# Ruby
{"a simple float"=>2.0, "larger float"=>1000.09, "scientific notation"=>1000.09}
时间
# Yaml
iso8601: 2001-12-14t21:59:43.10-05:00
space seperated: 2001-12-14 21:59:43.10 -05:00
# Ruby
{"iso8601"=>2001-12-15 10:59:43 +0800, "space seperated"=>2001-12-15 10:59:43 +0800}
日期
# Yaml
--- 1976-07-31
# Ruby
#<Date: 1976-07-31 ((2442991j,0s,0n),+0s,2299161j)>
强制转型
YAML 的自动判定数据形态是哪一种实体。但有时用户会想要将数据强制转型成自定的某种类型。最常见的状况是字符串,有时候可能看起来像数字或布尔值,这种时候可以使用双引号,或是使用严格类型标签。
# Yaml
---
a: 123 # 整数
b: "123" # 字串(使用双引号)
c: 123.0 # 浮点数
d: !!float 123 # 浮点数,使用!!表示的严格类型
e: !!str 123 # 字串,使用严格类型
f: !!str Yes # 字串,使用严格类型
g: Yes # 布尔值"真"
h: Yes we have No bananas # 字串(包含"Yes"和"No")
# Ruby
{"a"=>123,
"b"=>"123",
"c"=>123.0,
"d"=>123.0,
"e"=>"123",
"f"=>"Yes",
"g"=>true,
"h"=>"Yes we have No bananas"}
区块字符
保存新行
# Yaml
data: |
Wrapped text # 折叠的文字
will be folded # 将会被收
into a single # 进单一一个
paragraph # 段落
Blank lines denote # 空白的行代表
paragraph breaks # 段落直接的间隔
# Ruby
{"data"=>
"Wrapped text # 折叠的文字\n" +
"will be folded # 将会被收\n" +
"into a single # 进单一一个\n" +
"paragraph # 段落\n" +
"\n" +
"Blank lines denote # 空白的行代表\n" +
"paragraph breaks # 段落直接的间隔"}
折叠新行
# Yaml
data: >
Wrapped text # 折叠的文字
will be folded # 将会被收
into a single # 进单一一个
paragraph # 段落
Blank lines denote # 空白的行代表
paragraph breaks # 段落直接的间隔
# Ruby
{"data"=>
"Wrapped text # 折叠的文字 will be folded # 将会被收 into a single # 进单一一个 paragraph # 段落\n" +
"Blank lines denote # 空白的行代表 paragraph breaks # 段落直接的间隔"}
和保存新行不同的是,换行字符会被转换成空白字符。而引领空白字符则会被自动消去。
数据合并和参考
有点类似于大部分语言当中类的定义和继承的关系,如果定义有冲突,以子类的为准。
# Yaml
---
- step: &id001 # 锚点标签标签 &id001
instrument: Lasik 2000
pulseEnergy: 5.4
pulseDuration: 12
repetition: 1000
spotSize: 1mm
- step:
<<: *id001 # 合并键值:使用在锚点标签定义的內容
spotSize: 2mm #
- step:
<<: *id001 # 合并键值:使用在锚点标签定义的內容
pulseEnergy: 500.0 # 覆盖键值
alert: > # 加入其他键值
warn patient of
audible pop
# Ruby
[{"step"=>
{"instrument"=>"Lasik 2000",
"pulseEnergy"=>5.4,
"pulseDuration"=>12,
"repetition"=>1000,
"spotSize"=>"1mm"}},
{"step"=>
{"instrument"=>"Lasik 2000",
"pulseEnergy"=>5.4,
"pulseDuration"=>12,
"repetition"=>1000,
"spotSize"=>"2mm"}},
{"step"=>
{"instrument"=>"Lasik 2000",
"pulseEnergy"=>500.0,
"pulseDuration"=>12,
"repetition"=>1000,
"spotSize"=>"1mm",
"alert"=>"warn patient of audible pop"}}]