How to compare keys in yaml files?

后端 未结 4 938
醉梦人生
醉梦人生 2021-02-14 15:27

There are two ruby on rails internationalization yaml files. One file is complete and another one is with missing keys. How can I compare two yaml files and see missing keys in

相关标签:
4条回答
  • 2021-02-14 15:57

    Assuming file1 is the proper version and file2 is the version with missing keys:

    def compare_yaml_hash(cf1, cf2, context = [])
      cf1.each do |key, value|
    
        unless cf2.key?(key)
          puts "Missing key : #{key} in path #{context.join(".")}" 
          next
        end
    
        value2 = cf2[key]
        if (value.class != value2.class)
          puts "Key value type mismatch : #{key} in path #{context.join(".")}" 
          next
        end
    
        if value.is_a?(Hash)
          compare_yaml_hash(value, value2, (context + [key]))  
          next
        end
    
        if (value != value2)
          puts "Key value mismatch : #{key} in path #{context.join(".")}" 
        end    
      end
    end
    

    Now

    compare_yaml_hash(YAML.load_file("file1"), YAML.load_file("file2"))
    

    Limitation: Current implementation should be extended to support arrays if your YAML file contains arrays.

    0 讨论(0)
  • 2021-02-14 16:05

    differz compares two YAML files and prints missing keys in the second file.

    It comes both as a library and as a command-line tool. You can install the latter with gem install differz.

    0 讨论(0)
  • 2021-02-14 16:10

    I wanted to extract the diff to have something to work with, and the snippet here just prints stuff. So my version returns a hash with diff. It's structure mirrors the original hashes, but the values are descriptions of the differences.

    def deep_hash_diff(hash1, hash2, hash1_name = 'Hash 1', hash2_name = 'Hash 2')
      diff = {}
      (hash1.keys - hash2.keys).each do |key1|
        diff[key1] = "Present in #{hash1_name}, but not in #{hash2_name}"
      end
      (hash2.keys - hash1.keys).each do |key2|
        diff[key2] = "Present in #{hash2_name}, but not in #{hash1_name}"
      end
    
      (hash1.keys & hash2.keys).each do |common_key|
        if hash1[common_key].is_a?(Hash)
          if hash2[common_key].is_a?(Hash)
            res = deep_hash_diff(hash1[common_key], hash2[common_key], hash1_name, hash2_name)
            diff[common_key] = res if res.present?
          else
            diff[common_key] = "#{hash1_name} has nested hash, but #{hash2_name} just value #{hash2[common_key]}"
          end
        elsif hash2[common_key].is_a?(Hash)
          diff[common_key] = "#{hash2_name} has nested hash, but #{hash1_name} just value #{hash1[common_key]}"
        end
      end
      diff
    end
    

    I've then used it pretty much as:

    res = deep_hash_diff(YAML.load_file("en.yml"), YAML.load_file("spa.yml"), 'English translation', 'Spanish translation')
    puts(res.to_yaml) # for nicer output
    
    0 讨论(0)
  • 2021-02-14 16:12

    I couldn't find a fast tool to do that. I decided to write my own tool for this.

    You can install it with cabal:

    $ cabal update
    $ cabal install yamlkeysdiff
    

    Then you can diff two files this way:

    $ yamlkeysdiff file1.yml file2.yml
    > missing key in file2
    < missing key in file1
    

    You can also compare two subsets of the files:

    $ yamlkeysdiff "file1.yml#key:subkey" "file2.yml#otherkey"
    

    It behaves exactly like diff, you can do this:

    $ yamlkeysdiff file1.yml file2.yml && echo Is the same || echo Is different
    
    0 讨论(0)
提交回复
热议问题