我该如何在Ruby中解析YAML文件?

248
我想知道如何解析一个具有以下内容的YAML文件:
--- 
javascripts: 
- fo_global:
  - lazyload-min
  - holla-min

目前我正在尝试以这种方式解析:

@custom_asset_packages_yml = (File.exists?("#{RAILS_ROOT}/config/asset_packages.yml") ? YAML.load_file("#{RAILS_ROOT}/config/asset_packages.yml") : nil)
    if !@custom_asset_packages_yml.nil?
      @custom_asset_packages_yml['javascripts'].each{ |js|
        js['fo_global'].each{ |script|
         script
        }
      }
    end

但似乎它不起作用,并给我一个值为空的错误。

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

如果我尝试这样做,它就会输出整个字符串(fo_globallazyload-minholla-min):

if !@custom_asset_packages_yml.nil?
          @custom_asset_packages_yml['javascripts'].each{ |js|
            js['fo_global']
          }
        end

1
当你运行脚本时,你能给出输出吗?文件放在正确的位置了吗?你总是可以启动Rails控制台,看看Ruby是否也能看到那个路径。 - Lukas
是的,文件确实存在并且位于正确的位置。我已经在我的帖子中更新了错误信息。 - alvincrespo
3个回答

522

也许我有所疏忽,但为什么要尝试解析文件呢?为什么不只是加载 YAML 并检查结果得到的对象(们)呢?

如果你的样本 YAML 存在于 some.yml 中,那么可以这样:

require 'yaml'
thing = YAML.load_file('some.yml')
puts thing.inspect

给我

{"javascripts"=>[{"fo_global"=>["lazyload-min", "holla-min"]}]}

10
我同意,这就是 YAML 的优点——我们可以将某些东西序列化,然后以后再读取它,那为什么不利用这种能力呢。 - the Tin Man
由于某些原因,我可以使用require yaml,但是我遇到了解析错误,然后我看到了一些关于Psych的内容。当我执行Psych.load("file.yml")时,它只输出“file.yml”部分而不是文件的实际内容。 - FilBot3
1
哦,原来是因为我在使用制表符。看起来它只接受空格而不是制表符,然后就会抛出各种错误。 - FilBot3
3
YAML库中,#load和#load_file有什么区别? - Jwan622
3
YAML.load 接受一个 YAML 字符串, YAML.load_file 接受一个相对文件路径。 - Narfanator
显示剩余2条评论

13

我曾经遇到过相同的问题,但我还想获取文件内容(YAML前置元数据之后的内容)。

这是我找到的最佳解决方案:

if (md = contents.match(/^(?<metadata>---\s*\n.*?\n?)^(---\s*$\n?)/m))
  self.contents = md.post_match
  self.metadata = YAML.load(md[:metadata])
end

来源和讨论:https://practicingruby.com/articles/tricks-for-working-with-text-and-files


1
链接现在似乎是https://practicingruby.com/articles/tricks-for-working-with-text-and-files。 - devstuff
谢谢 @devstuff - 我已经更新了答案中的链接。 - sarfata

5

以下是我使用的一条命令行命令,用于测试yml文件内容:

$ ruby  -r yaml -r pp  -e 'pp YAML.load_file("/Users/za/project/application.yml")'
{"logging"=>
  {"path"=>"/var/logs/",
   "file"=>"TacoCloud.log",
   "level"=>
    {"root"=>"WARN", "org"=>{"springframework"=>{"security"=>"DEBUG"}}}}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接