Ruby-YAML多文档

Ruby-YAML多文档,ruby,yaml,documents,Ruby,Yaml,Documents,这是我的YAML文件“test.yml”: --- alpha: 100.0 beta: 200.0 gama: 300.0 --- 3 ... 第一个文档是散列 第二个文档是一个整数 我试图将它们作为散列和整数加载到Ruby程序中 以下是我目前的尝试: require 'yaml' variables = YAML.load_file('test.yml') puts variables.inspect 不要使用多个文档;它们不能替代在数据中定义单个元素: require 'yaml'

这是我的YAML文件“test.yml”:

---
alpha: 100.0
beta: 200.0
gama: 300.0
--- 3
...
第一个文档是散列

第二个文档是一个整数

我试图将它们作为散列和整数加载到Ruby程序中

以下是我目前的尝试:

require 'yaml'

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

不要使用多个文档;它们不能替代在数据中定义单个元素:

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解析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"]}
foo:&1
定义了
[“foo”]
,并在底部被重用为
*1


“”是与YAML合作的一个很好的参考。

铁皮人正确地认为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}
需要“yaml”
yaml=100.0,“beta”=>200.0,“gama”=>300.0}
#>>{“int”=>3}

要访问单个文件中的多个YAML文档,请使用以下方法(如“matt”在对其他答案之一的评论中所述):


您应该只使用而不是自己做(注意
Psych
常量与当前Rubys中的
YAML
相同)。不幸的是,的ruby文档页面没有提供指向Psych文档的链接。它甚至没有提到公共界面除了加载、
转储
、和
到_yaml
@matt之外还有更多内容,你应该把你的评论作为答案发布,因为它实际上是对问题的正确答案,并且被零票覆盖。我注意到,Ruby 2.4.1,psych 2.2,使用
%YAML 1.2
作为“文档头”会导致Psych抛出错误,当然,在一些合理的用例中,您可能会希望使用多个文档。例如文档流。是的,但是在OP的例子中,使用多个文档不是正确的方法。答案不应该只是解决问题,他们还应该教育。我们看到了很多类型的问题,因此指出一种更合适的处理问题的方法也很重要。当然,通过指出在这种特定情况下,多个文档可能不是正确的方法来尝试使答案更精确一些可能是有用的。我主要考虑的是第一句话,听起来非常激烈。它看起来像是
#load_stream
接受YAML编码的字符串而不是文件名。是的,这应该是
YAML.load_stream(File.read('test.yml'))
,或者是带有块的调用。如果仅使用文件名,
load_stream
将返回
[“test.yml”]
,而不是包含流中两个已解析文档的数组。
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
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}
YAML.load_stream(File.read('test.yml')) do |document|
  puts document
end