使用 Ruby 数据结构理解 Yaml 基本语法

其实也无需了解得太深入,但是至少你得知道一个 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"}}]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值