我有一个查找文件,该文件将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”的数组。
有人可以在这里解释我在做什么错吗?
答案 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工具的创建者