从JQ中的外部文件查找ID

时间:2019-07-16 20:05:12

标签: jq

我有一个查找文件,该文件将ID从一个系统映射到另一个系统:

[
  {
    "idA": 2547,
    "idB": "5d0bf91d191c6554d14572a6"
  },
  {
    "idA": 2549,
    "idB": "5b0473f93d4e53db19f8c249"
  },
  {
    "idA": 2550,
    "idB": "5d0bfabc8f20917b92ff07dc"
  },
...

我有一个数据文件,其中包含来自这些系统之一的值和ID:

[
  {
    "idB": "5d0bf91d191c6554d14572a6",
    "description": "Description for 5d0bf91d191c6554d14572a6"
  },
  {
    "idB": "5d0bf49e9236c57281811cfc",
    "description": "Description for 5d0bf49e9236c57281811cfc"
  },
  {
    "idB": "5d0bfabc8f20917b92ff07dc",
    "description": "Description for 5d0bfabc8f20917b92ff07dc"
  },
...

我想生成描述的新文件,并将其ID转换为查找文件中的idA值。我尝试过:

jq --slurpfile idmap ids.json 'map( {"description":.description, "id": (.idB as $b|$idmap[][]|select(.idB==$b)|.idA) } )' descriptions.json

但是它只产生一个空数组。

我必须对$idmap进行双重引用,因为对文件进行草稿“将已解析的JSON值的数组绑定到给定的全局变量”,因此仅执行$idmap[]会引发错误, jq:错误(在descriptions.json:70处):无法索引字符串为“ idB”的数组

有人可以在这里解释我在做什么错吗?

2 个答案:

答案 0 :(得分:1)

这是解决上述问题的简洁明了的解决方案。

为简单起见,我们将首先使用INDEX/2构建一个包含相关映射的字典:

INDEX($idmap[]; .idB) | map_values(.idA)

现在任务很简单:

(INDEX($idmap[]; .idB) | map_values(.idA)) as $dict
| map( {description, "idA": $dict[.idB] } )

这假设调用使用--argfile idmap ids.json来避免 由--slurpfile引起的不必要的“拖拉”,但是,如果使用后者,那么您将使用$idmap[][]代替原来的问题。

由于示例代码段不包含任何匹配的“ idB”值,因此显示使用这些代码段可获得的输出毫无意义。

变化

如果descriptions.js中的对象还有其他应保留的键,则以下变体可能是更有用的指南:

(INDEX($idmap[]; .idB) | map_values(.idA)) as $dict    # or $idmap[][] as above
| map( .idA = $dict[.idB] | del(.idB) )

答案 1 :(得分:0)

或者,可以使用基于步行路径的Unix实用程序 jtc

bash $ <descriptions.json jtc -w'<idB>l:<I>v' -u ids.json -u'<I>s[-1][idA]'
[
   {
      "description": "Description for 5d0bf91d191c6554d14572a6",
      "idB": 2547
   },
   {
      "description": "Description for 5d0bf49e9236c57281811cfc",
      "idB": "5d0bf49e9236c57281811cfc"
   },
   {
      "description": "Description for 5d0bfabc8f20917b92ff07dc",
      "idB": 2550
   }
]
bash $ 

目的地遍历(-w'<idB>l:<I>v')将遍历每个标记为idB(在文件descriptions.json中的条目),并将存储在命名空间I遍历值中。

对于每个步行-w,都会有一个相应的更新(重写)步行(-u'<I>s[-1][idA]')。它将在源文件ids.json中递归搜索存储在名称空间I中的值,然后(如果找到)返回上一级并选择标记为idA的值,从而有效地获取更新/重写所需的ID。

PS>披露:我是jtc-用于JSON操作的shell cli工具的创建者