【问题标题】:Merge yaml files and re-organize by values of key value list合并yaml文件并按键值列表的值重新组织
【发布时间】:2019-12-26 10:28:59
【问题描述】:

我有一个 yaml 文件列表,每个文件都描述一个项目,并带有一个键 sdgs,其中包含代表可持续发展目标的数字列表。

我想合并所有文件并将它们转换为不同格式的json,以sdg索引为键,相关项目为列表值。

输入:

---
# gnu_health.yaml
description: >
  GNU Health is a Free/Libre project for health practitioners, health
  institutions and governments. It provides the functionality of Electronic
  Medical Record (EMR), Hospital Management (HMIS) and Health Information
  System (HIS).
sdgs: [3]
name: GNU Health 

---
# a11y.yaml
description: >
  This Accessibility Project is a community-driven effort to make web
  accessibility easier by leveraging a worldwide community of developer
  knowledge.
sdgs: [10]
name: A11Y

---
# bahmni.yaml
description: >
  Bahmni is an Open Source hospital Management System focusing
  on poor/underserved and public hospitals in the developing
  world.
  It's aimed to being a generic system which can be used for
  multiple diseases and hospitals in different countries.
sdgs: [1, 3]
name: Bahmni

预期输出

{
  "1": [
    {
      "name": "Bahmni",
      "description: "..."
    }
  ],
  "3": [
    {
      "name": "GNU Health",
      "description: "..."
    },
    {
      "name": "Bahmni",
      "description: "..."
    }
  ],
  "10": [
    {
      "name: "A11Y",
      "description: "..."
    }
  ]
}

即使在阅读了 manual 和其他 awesome-jq 资源之后,我也发现使用 jq 的过滤系统很难解决这个问题。

有人能指出正确的方向吗?

目前的最大努力:

# use as follow: yq -f $binDir/concat_sdgs.jq $srcDir/*.y*ml

# concat_sdgs.jq
{
  (.sdgs[]|tostring): [.]
}

不幸的是,这不会将来自同一个 sdg 的项目合并在一起

当前输出不正确

{
  "1": [
    {
      "name": "Bahmni",
      "description: "..."
    }
  ],
  "3": [
    {
      "name": "GNU Health",
      "description: "..."
    }
  ],
  "3": [
    {
      "name": "Bahmni",
      "description: "..."
    }
  ],
  "10": [
    {
      "name: "A11Y",
      "description: "..."
    }
  ]
}

【问题讨论】:

    标签: json yaml jq


    【解决方案1】:

    好消息是你很接近了。

    为简单起见,我假设 .yaml 到 .json 的转换已经完成。稍微调整一下你的过滤器,很容易看出:

    jq '{ (.sdgs[]|tostring): del(.sdgs) }' a11y.json gnu_health.json bahmni.json
    

    生成与您想要的非常对应的四个单键对象的流。

    将它们组合成一个对象有点棘手。为简单起见,我们首先定义一个辅助函数,它可以用于按键对单键对象进行分组:

      def group_by_keys: reduce .[] as $o ({}; 
         reduce ($o | to_entries[]) as $kv (.; .[$kv.key]
    

    接下来,我们将使用带有 -n 命令行选项的 inputs

    jq -n '
      def group_by_keys: reduce .[] as $o ({}; 
         reduce ($o | to_entries[]) as $kv (.; .[$kv.key] += [$kv.value]));
      [inputs | {(.sdgs[]|tostring): del(.sdgs) }] | group_by_keys
    
    ' a11y.json gnu_health.json bahmni.json
    
    

    (别忘了-n。)

    如果键的顺序很重要,那么只需使用这个过滤器:

    def sort_by_keys:
      to_entries
      | sort_by(.key|tonumber)
      | from_entries;
    

    【讨论】:

    • 感谢您的回复。不幸的是,这似乎并没有产生预期的结果。我没有为每个 sdg 键列出一个项目列表,而是将一个项目视为 sdg 的对象值。如果我可以为每个 sdg 连接项目,这将是完美的
    • 我正在做 -n。它仍然只在输出中列出每个 sdg 的 1 个项目。如果您尝试使用 3 个文件运行此程序,其中 2 个文件为 sdg: [3],则只会返回一个项目
    • 对不起,我已经用一个更好的例子更新了这个问题:)
    • debug 是开始调试的好地方。我认为您会发现花时间掌握 reduceto_entries 系列过滤器是值得的。
    猜你喜欢
    • 2017-10-26
    • 2017-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-11
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多