2013-08-22 66 views
4

我是YAML和Ruby的新手。我使用下面的Ruby代碼解析YAML文件:關於YAML語法和Ruby解析的說明

obj = YAML::load_file('test.yml') 

是「test.yml」有效以下YAML文件內容是什麼?

案例1:

test 

在這種情況下,我沒有指定的test(像test : true),但我的Ruby解析代碼不拋出一個錯誤值。我認爲這是一個無效的YAML語法。

案例2:

:test : true 

在這種情況下,Ruby代碼把test爲標誌,而不是一個字符串,當我做puts obj[:test],它返回的結果爲「真」。這是一個Ruby的東西?其他語言會將其解釋爲字符串":test"

案例3:

:test : true 
:test : false 

在這種情況下,不是拋出了一個錯誤的:test重新定義的,我的Ruby代碼花費:test的最新值(這是false)。爲什麼是這樣? YAML語法是否允許重新定義元素,並且在這種情況下只採用最新值?

+0

您將從閱讀http://www.yaml.org/YAML_for_ruby.html中獲益。另外,我們需要看到一個更好的YAML例子,它正在被解析。 –

回答

4

案例1: YAML允許unquoted scalars或「裸」字符串不包含在引號中。與引用的字符串相比,它們不太靈活,因爲您不能使用某些字符而不創建模糊的語法,但Ruby解析器確實支持它們。

1.9.3-p448 > YAML::parse('test').to_ruby 
=> "test" 

案例2:正如你已經猜到,這是Ruby的特異性的,因爲YAML沒有「符號」的概念。將YAML mapping轉換爲Ruby哈希時,以冒號開頭的標量鍵被解釋爲符號而不是字符串。

案例3:根據YAML定義的mapping,鍵必須是唯一的,所以嚴格的解析器應該在給定示例時拋出錯誤。看起來Ruby解析器更加寬鬆,並允許使用last-value-win規則多次定義相同的密鑰。這在本地Ruby哈希中也是允許的。

1.9.3-p448 > YAML::parse("test: true\ntest: false").to_ruby 
=> {"test"=>false} 
1.9.3-p448 > { 'test' => true, 'test' => false } 
=> {"test"=>false} 
+0

感謝Grantovich您的時間和答覆。在案例1中,我看到內容被反序列化爲一個字符串而不是哈希。我一直認爲YAML :: load_file總是返回一個Hash。另外,不加引號的標量的目的是什麼?在案例1中,我想Ruby會自動解析一個像「test」這樣的未加引號的標量,並將其放入哈希中。 –

+0

另一個問題可能不一定與這個話題有關。我試圖想出一個設計,在這裏我將有一個基本選項文件,它有一些選項的值,並且覆蓋文件,如果需要的話會改變這些選項。實質上,我正在利用案例3中提到的Ruby解析器的非嚴格性。請讓我知道它是否是一個好設計? –

+0

關於您的第一條評論,'YAML :: load_file'只是返回一個YAML文檔的Ruby表示。 YAML文檔可以包含數組,哈希和字符串的任何組合 - 沒有規則說明它必須是單個哈希。如果這對你來說是新鮮的,維基百科的文章(http://en.wikipedia.org/wiki/YAML)提供了一個關於YAML文檔如何工作的體面的概述。 – Grantovich

2

一個偉大的方式來學習如何YAML解析器轉換成/ Ruby中的結構,是寫輸出YAML Ruby代碼,看看它在做什麼:

這是一個基本的散列:

require 'yaml' 
foo = {'test' => true} # => {"test"=>true} 
foo.to_yaml # => "---\ntest: true\n" 

使用符號作爲密鑰的哈希:

foo = {test: true} 
foo.to_yaml # => "---\n:test: true\n" 

具有衝突密鑰哈希,使第e首先被踩到最後:

foo = {test: true, test: false} 
foo # => {:test=>false} 
foo.to_yaml # => "---\n:test: false\n" 

YAML正在創建散列,但散列不能有重複的鍵;如果他們這樣做,碰撞會導致第二個替換第一個。

Yaml Cookbook at the YamlForRuby site」也是一個很好的資源。