如何使用jq筛选fileA中id存在于fileB的JSON对象?
用jq基于另一个JSON文件的字段筛选对象
需求说明
需要从fileA的JSON数组里,筛选出id字段存在于fileB的JSON数组theId字段中的对象,排序不做要求。
fileA的JSON内容
[ { "id": "bird", "content": { "key1": "a" } }, { "id": "dog", "content": { "key1": "b" } }, { "id": "cat", "content": { "key1": "c" } } ]
fileB的JSON内容
[ { "theId": "cat" }, { "theId": "bird" } ]
预期结果(排序无关)
[ { "id": "cat", "content": { "key1": "c" } }, { "id": "bird", "content": { "key1": "a" } } ]
原尝试方案(不够优雅)
之前考虑用bash循环遍历fileB里的theId值,每次执行下面的jq命令提取对应对象:
jq -c "map(select(.id | contains(\"$id\")))"
但这种方式需要手动处理结果的逗号分隔,太麻烦,想找个让jq直接用fileB的数组值当筛选条件的方法。
优雅的jq实现
可以利用jq的参数把fileB内容加载成变量,构建ID集合来筛选,既高效又不用额外处理格式:
方法一:用--slurpfile参数
jq --slurpfile ids fileB.json ' ($ids[0] | map(.theId) | INDEX(.)) as $idSet | map(select($idSet[.id])) ' fileA.json
方法二:用-s参数多文件输入
jq -s ' .[1] as $fileB | ($fileB | map(.theId) | INDEX(.)) as $idSet | .[0] | map(select($idSet[.id])) ' fileA.json fileB.json
代码说明
map(.theId):从fileB的数组里提取所有theId值,得到纯ID数组。INDEX(.):把ID数组转成以ID为键的对象(类似哈希集合),判断ID是否存在的操作是O(1),比遍历数组快很多。map(select($idSet[.id])):遍历fileA的数组,只保留id在集合里的对象。
内容的提问来源于stack exchange,提问作者B Jam
相关产品推荐
相关产品推荐

