2013-10-11 67 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