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

When I parse YAML with Ruby, it changes my anchor name

我有一个像这样的 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

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

您可以使用 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

说明

使用标准 load/dump 这是不可能的,因为标签信息丢失了。再次转储已解析的 YAML 时发生的情况相当于:

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

###

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

应用任意 ID 来标记对象。

但你并非倒霉!通过下降到 psych 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 returns 是一个 AST 而不是普通的 ruby 对象,所以现在的技巧是更新那个 AST,这比你之前的更难,也可能更脆弱试。如果您 pp parse_stream 的 return 值,则结构很容易理解,您可以编写一些代码,如顶部的答案。