2013-10-11 68 views
5

這裏是我的YAML文件, 'test.yml':紅寶石YAML多個文檔

--- 
alpha: 100.0 
beta: 200.0 
gama: 300.0 
--- 3 
... 

第一份文件是一個散列。

第二個文檔是一個整數。

我想加載到一個Ruby程序作爲一個哈希和一個整數。

這裏是我當前的嘗試:

require 'yaml' 

variables = YAML.load_file('test.yml') 
puts variables.inspect 

回答

0

不要使用多個文件;他們不是在你的數據定義單個元素的替代品:

require 'yaml' 

yaml = <<EOT 
--- 
hash: 
    alpha: 100.0 
    beta: 200.0 
    gama: 300.0 
int: 3 
EOT 

YAML.load(yaml) 
# => {"hash"=>{"alpha"=>100.0, "beta"=>200.0, "gama"=>300.0}, "int"=>3} 

可以通過分配YAML.load(yaml)給一個變量訪問內容:

data = YAML.load(yaml) 
data['hash'] # => {"alpha"=>100.0, "beta"=>200.0, "gama"=>300.0} 
data['int'] # => 3 

認爲它這樣,你問在分析YAML文件之後從YAML獲取某種對象。你需要能夠從中提取特定的值,所以在YAML的限制和規格範圍內,使自己變得容易並定義一個包含你想要的數組或哈希的方式,以一種符合你的大腦的方式工作。

如果我將要創建一個複雜的結構,我這樣做是在Ruby中第一,並有YAML轉儲我的格式爲:

require 'yaml' 

data = { 
    "hash" => { 
    "alpha" => 100.0, 
    "beta" => 200.0, 
    "gama" => 300.0 
    }, 
    "int" => 3 
} 

puts data.to_yaml 

# >> --- 
# >> hash: 
# >> alpha: 100.0 
# >> beta: 200.0 
# >> gama: 300.0 
# >> int: 3 

我可以把Ruby代碼到一個腳本並運行它,它重定向到一個YAML文件:

ruby test.rb > test.yaml 

然後我就可以展開結構:

require 'yaml' 

data = { 
    "hash" => { 
    "alpha" => 100.0, 
    "beta" => 200.0, 
    "gama" => 300.0 
    }, 
    "int" => 3, 
    "array" => %w[a b c] 
} 

puts data.to_yaml 

# >> --- 
# >> hash: 
# >> alpha: 100.0 
# >> beta: 200.0 
# >> gama: 300.0 
# >> int: 3 
# >> array: 
# >> - a 
# >> - b 
# >> - c 

測試它往返:

require 'yaml' 

yaml = <<EOT 
--- 
hash: 
    alpha: 100.0 
    beta: 200.0 
    gama: 300.0 
int: 3 
array: 
- a 
- b 
- c 
EOT 

YAML.load(yaml) 
# => {"hash"=>{"alpha"=>100.0, "beta"=>200.0, "gama"=>300.0}, "int"=>3, "array"=>["a", "b", "c"]} 

迭代做到這一點,直到你滿意YAML語法,那麼你可以建立/手動調整你的YAML文件。

現在,這裏有多聰明。 YAML規範支持別名,它允許我們定義一個變量,然後分別使用&*多次重複使用它。創建這些手工是一種痛苦時,你的文件變大,但YAML司機很聰明,會輸出他們爲你:

require 'yaml' 

FOO = ['foo'] 
BAR = ['bar'] 

foobar = [FOO, BAR] 

data = { 
    "foo" => FOO, 
    'bar' => BAR, 
    'foobar' => foobar, 
} 

puts data.to_yaml 


# >> --- 
# >> foo: &1 
# >> - foo 
# >> bar: &2 
# >> - bar 
# >> foobar: 
# >> - *1 
# >> - *2 

foo: &1定義["foo"],並在底部的*1得到重用。

Yaml Cookbook at the YamlForRuby site」是與YAML合作的重要參考。

+0

有合理使用您想要使用多個文檔的情況。例如文檔流。 –

+0

是的,但在OP的情況下,使用多個文檔並不是正確的方法。答案不應該只是解決問題,他們也應該教育。我們看到很多[XY問題](http://xyproblem.info)類型的問題,因此指出處理問題的更合適的方式也很重要。 –

+0

當然,通過指出在這個特定情況下多個文檔可能不是正確的方法,試圖使答案更加精確可能會有所幫助。我主要想的是第一句話,聽起來很激烈。 –

4

錫文是正確的,OP不應該爲他的具體問題使用多個文件;然而,實際上YAML流中的多個文檔的情況確實發生,例如,當多個YAML文檔被附加到單個文件時,所以值得知道如何處理它。

require 'yaml' 

yaml = <<EOT 
--- 
alpha: 100.0 
beta: 200.0 
gama: 300.0 
--- 
int: 3 
... 
EOT 

loop do 
    puts YAML.load(yaml) 
    break if !yaml.sub!(/(?<!#)(-{3}.+?(?=-{3})\n?){1}/m,'') 
    break if yaml.empty? 
end 

# >> {"alpha"=>100.0, "beta"=>200.0, "gama"=>300.0} 
# >> {"int"=>3} 
+8

你應該只使用['load_stream'](http://ruby-doc.org/stdlib-2.1.0/libdoc/psych/rdoc/Psych.html#method-c-load_stream)而不是自己做(注意在當前的Rubys中,'Psych'常數與'YAML'相同)。 – matt

+2

不幸的是,[YAML]的ruby-doc頁面(http://ruby-doc.org/stdlib-2.1.0/libdoc/yaml/rdoc/YAML.html)沒有提供一個鏈接到Psych文檔。它甚至沒有提到公共接口比'load','dump'和'to_yaml'更多。 –

+1

@matt您應該將您的評論作爲答案發布,因爲它實際上是問題的正確答案,它被埋在零票答案中。 –

10

訪問多個YAML文件在一個單一的文件,使用load_stream方法(如已被「亞光」在評論中提及到的其他答案之一):

YAML.load_stream('test.yml') do |document| 
    puts document 
end