Как сравнить ключи в файлах yaml? - PullRequest
10 голосов
/ 08 июня 2011

Есть два файла yaml интернационализации ruby ​​на рельсах.Один файл завершен, а другой с отсутствующими ключами.Как я могу сравнить два файла yaml и увидеть недостающие ключи во втором файле?Есть ли инструменты для этого?

Ответы [ 3 ]

13 голосов
/ 08 июня 2011

Предполагается, что file1 - правильная версия, а file2 - версия с отсутствующими ключами:

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

Теперь

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

Ограничение: Текущая реализация должна быть расширена для поддержки массивов, если ваш файл YAML содержит массивы.

2 голосов
/ 23 июля 2015

Я не мог найти быстрый инструмент для этого. Я решил написать свой собственный инструмент для этого.

Вы можете установить его с помощью cabal:

$ cabal update
$ cabal install yamlkeysdiff

Тогда вы можете различить два файла следующим образом:

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

Вы также можете сравнить два подмножества файлов:

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

Он ведет себя так же, как diff, вы можете сделать это:

$ yamlkeysdiff file1.yml file2.yml && echo Is the same || echo Is different
0 голосов
/ 27 июня 2018

Я хотел извлечь diff, чтобы было с чем работать, а фрагмент здесь просто печатает материал. Так что моя версия возвращает хеш с diff. Его структура отражает исходные хэши, но значения являются описаниями различий.

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

Я тогда использовал это как:

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
...