JQ筛选不含指定精确匹配值JSON元素取反异常如何解决
jq嵌套数组反选指定值实现方法
问题场景
待处理的JSON为多层嵌套结构,存储了水果名称和对应标签数据,示例结构如下:
{ "data":[ { "name":"banana", "tags":[ {"id":"yellow"}, {"id":"long"} ] }, { "name":"apple", "tags":[ {"id":"red"}, {"id":"round"} ] }, { "name":"orange", "tags":[ {"id":"orange"}, {"id":"round"}, {"id":"colored"} ] } ] }
需求为筛选出标签中不存在*指定关键词(以"red"为例)*的元素。
原有命令异常原因
之前使用的正向匹配命令:
jq '.data[] | select(.tags[].id | index( "red" ))'
存在两处逻辑缺陷:
- 直接使用
.tags[]会遍历标签数组的每一项,每匹配到一个符合条件的标签,就会输出一次对应的父对象。添加not取反后,只要对象存在任意一个不匹配关键词的标签,就会触发一次输出,最终导致同一元素重复返回。 index("red")为子串匹配规则,并非精确等值匹配,因此id为colored的标签会因为包含red子串被误命中。
正确实现方案
筛选时需要对整个标签数组做全量判断,避免直接展开数组导致重复输出,根据匹配精度要求选择对应命令即可:
- 精确匹配场景:仅当标签id完全等于
red时才排除对应元素
执行后返回jq '.data[] | select(all(.tags[].id; . != "red"))'banana、orange两个元素,无重复。 - 子串匹配场景:只要标签id包含
red子串就排除对应元素
执行后仅返回jq '.data[] | select(all(.tags[].id; index("red") | not))'banana元素,apple(存在精确匹配red的标签)、orange(colored含red子串)都会被排除。
逻辑补充
all(遍历逻辑; 判断条件)会校验遍历得到的所有值是否全部满足判断条件,仅当全部满足时返回true,不会展开数组造成重复输出。- 如果需要正向筛选「至少有一个标签符合匹配规则」的元素,将命令中的
all替换为any即可,同样不会出现元素重复的问题。
内容的提问来源于stack exchange,提问作者faceless
相关产品推荐
相关产品推荐

