使用ruby更新yml文件中键值对的值

时间:2016-01-22 21:18:03

标签: ruby yaml jruby

我有一个YAML文件:

DATA_SVC_GEN_CONF_ATTR:
   -
     -   
       - 
         name: validationCodeNum
         value: 1
       - 
         name: validationCodeSymbol
         value: "val1"
       - 
         name: sql
         value: Test
       - 
         name: sqlByGridArea
         value: Test1

我想将键sql的值从“Test”替换为“Select * from table”。

我正在尝试的是:

asset.getAttributes.getList.each{|a|

  if a.getName == "sqlByGridArea"
     a.setValue "Select * from table"

    (attrib_defs).map!{|a| a.map{|k,v| "#{k}=#{v}"}.join(',')}
  end
   asset.with_attributes attrib_defs

1 个答案:

答案 0 :(得分:1)

以下是如何测试您的YAML是否有效,以及如何生成YAML以供在文件或其他地方使用:

require 'yaml'

str = <<EOT
DATA_SVC_GEN_CONF_ATTR:
   -
     -   
       - 
         name: validationCodeNum
         value: 1
       - 
         name: validationCodeSymbol
         value: "val1"
       - 
         name: sql
         value: Test
       - 
         name: sqlByGridArea
         value: Test1
EOT

data = YAML.load(str)
# => {"DATA_SVC_GEN_CONF_ATTR"=>
#      [[[{"name"=>"validationCodeNum", "value"=>1},
#         {"name"=>"validationCodeSymbol", "value"=>"val1"},
#         {"name"=>"sql", "value"=>"Test"},
#         {"name"=>"sqlByGridArea", "value"=>"Test1"}]]]}

如果YAML无法解析数据,他们会抱怨。如果可以,数据不是您所期望的,那么输出可以帮助您诊断问题。

当我想创建一个YAML文件,特别是一个复杂的文件时,我从实际的数据结构开始,让YAML生成它的序列化版本:

data = {
  'DATA_SVC_GEN_CONF_ATTR' =>
  [
    [
      [
        {
          'name' => 'validationCodeNum',
          'value' => 1
        },
        {
          'name' => 'validationCodeSymbol',
          'value' => 'val1'
        },
        {
          'name' => 'sql',
          'value' => 'Test'
        },
        {
          'name' => 'sqlByGridArea',
          'value' => 'Test1'
        }
      ]
    ]
  ]
}
puts data.to_yaml
# >> ---
# >> DATA_SVC_GEN_CONF_ATTR:
# >> - - - name: validationCodeNum
# >>       value: 1
# >>     - name: validationCodeSymbol
# >>       value: val1
# >>     - name: sql
# >>       value: Test
# >>     - name: sqlByGridArea
# >>       value: Test1

继续...要更改YAML文件中的元素,您可以将文件视为文本,逐行读取,通过啜饮来读取它,或者让YAML打开它并更改生成的对象然后使用YAML重写它。

如果您确定数据适合内存并且您可以轻松找到要更改的部分,则可以使用Slurping文件。逐行阅读通常会使查找特定文本变得更加容易,因为您处理的是单个行,而不是整个文件。

使用YAML是我认为最容易的,因为它减少了写错误的正则表达式的变化。

data = <<EOT
---
DATA_SVC_GEN_CONF_ATTR:
- - - name: validationCodeNum
      value: 1
    - name: validationCodeSymbol
      value: val1
    - name: sql
      value: Test
    - name: sqlByGridArea
      value: Test1
EOT

假设data是磁盘上YAML文件的内容,它将使用YAML.load_file加载和解析。在这个例子中,我以字符串形式加载,因此我必须使用load

object = YAML.load(data)

现在解析数据,以便轻松操作:

object['DATA_SVC_GEN_CONF_ATTR'].first.first[2]['name'] = "Select * from table"

然后可以写回来:

puts object.to_yaml # => nil
# >> ---
# >> DATA_SVC_GEN_CONF_ATTR:
# >> - - - name: validationCodeNum
# >>       value: 1
# >>     - name: validationCodeSymbol
# >>       value: val1
# >>     - name: Select * from table
# >>       value: Test
# >>     - name: sqlByGridArea
# >>       value: Test1

如果这是一个任务关键型(生产)文件,您需要执行适当的重命名,写入,删除步骤以保护数据以防出错,但这是要点它

但您的数据结构非常值得怀疑。您只是使用嵌套的数组数组来保存哈希值,这种情况并不常见或易于理解。相反,它应该简化为一个数组:

data = <<EOT
---
DATA_SVC_GEN_CONF_ATTR:
 - name: validationCodeNum
   value: 1
 - name: validationCodeSymbol
   value: val1
 - name: sql
   value: Test
 - name: sqlByGridArea
   value: Test1
EOT

object = YAML.load(data)
# => {"DATA_SVC_GEN_CONF_ATTR"=>
#      [{"name"=>"validationCodeNum", "value"=>1},
#       {"name"=>"validationCodeSymbol", "value"=>"val1"},
#       {"name"=>"sql", "value"=>"Test"},
#       {"name"=>"sqlByGridArea", "value"=>"Test1"}]}
object['DATA_SVC_GEN_CONF_ATTR'][2]['name'] = "Select * from table"