当我用Ruby解析YAML时,它会改变我的锚名称

时间:2015-02-16 15:20:39

标签: ruby anchor yaml

我有一个像这样的YAML文件:

    - axis: &kadeployversion
   type: user-defined
   name: kadeployversion
   values:
    - kadeploy3
    - kadeploy3-dev

我用Ruby编辑了这个文件:

require 'yaml'
jjb = YAML.load_file(fileToParse)
jjb[0]['type']='test'
File.open(fileToParse, 'w+'){
 |f| f.write jjb.to_yaml
}

但是当我读到我的新文件时,我有这个:

    - axis: &12345678
   type: test
   name: kadeployversion
   values:
    - kadeploy3
    - kadeploy3-dev

它有效,但我想保留原来的主播名称,否则它将变得不可读。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

您可以使用mid-level parsing API

来实现这一目标
stream   = Psych.parse_stream(yaml)
document = stream.children[0]
mapping  = document.children[0]
index    = mapping.children.index {|x|
  x.is_a?(Psych::Nodes::Scalar) && x.value == 'type'
}
mapping.children[index + 1].value = "new type"

puts stream.to_yaml

说明

使用标准加载/转储是不可能的,因为标签信息会丢失。再次转储已解析的YAML时发生的情况等同于:

a = [3]
puts({"version"=>a, "axis"=>a}.to_yaml)

###

---
version: &1
- 3
axis: *1

应用任意ID来标记对象。

但你不是运气不好!通过下降到心理mid-level parsing API,此数据存在,您可以使用它。

yaml = <<EOS
version: &kadeployversion
 - 3
axis: *kadeployversion
type: something
EOS

puts Psych.parse_stream(yaml).to_yaml
###
version: &kadeployversion
- 3
axis: *kadeployversion
type: something

parse_stream返回一个AST而不是普通的ruby对象,所以现在的诀窍就是更新那个AST,这比你一直尝试的更难和可能更脆弱。如果你pp parse_stream的返回值,希望结构很容易遵循,你可以在顶部编写一些代码,如答案。