如何用单条jq语句处理未知嵌套深度的JSON删除操作
问题描述
更新记录
- 更新2:使用递归
..确实能处理任意深度的JSON结构,当匹配type == "cow"或type == "lion"时,可按要求返回简化或保留父结构的结果。 - 更新1:调整JSON结构贴合真实场景后,添加
any()能正确删除.car[]、.boat[]的匹配值,但.plane的整条记录会被误删。
需求
需要修改jq语句实现两种输出:
- 匹配
type == "dog"时,删除car下包含该类型的子节点,保留car及其他子节点:
jq 'del(.car[], .boat[], .plane | select(any(.type == "dog")))' // 预期输出 { ... "car":{ "delta": {...} } ... }
- 匹配
type == "lion"时,删除plane下包含该类型的子节点,保留plane及其他子节点:
jq 'del(.car[], .boat[], .plane | select(any(.type == "lion")))' // 预期输出 { ... "plane":{ "delta": {} } ... }
尝试过的方法
曾尝试用select(.[-1] == "lion")替换select(.[].type == "lion"),但未生效;调整左侧路径为... .plane[]) | select(.type == "lion")?时,.car[]的匹配逻辑会失效。
核心问题
如何用单条jq语句处理未知嵌套深度的场景(比如car > type为3层,plane > type为2层),平衡路径选择和条件匹配的深度,只删除目标子节点而保留父结构。
测试用JSON结构
{ "www":"hello", "car": { "alpha": { "in": { "model": "alpha", "dir": "in", "type": "dog" }, "out": { "model": "alpha", "dir": "out", "type": "dog" } }, "delta": { "in": { "model": "delta", "dir": "in", "type": "bird" }, "out": { "model": "delta", "dir": "out", "type": "bird" } } }, "boat":{ "beta": { "in": { "model": "beta", "dir": "in", "type": "mouse" } } }, "plane":{ "beta": { "model": "beta", "dir": "in", "type": "lion" }, "delta": { "model": "delta", "dir": "in", "type": "bee" } } }
解决方案
使用递归遍历..结合any(),针对car、boat、plane的直接子节点进行筛选,删除那些自身或后代包含目标type值的节点:
匹配type == "dog"的语句
del( .car[] | select(any(..; .type == "dog")), .boat[] | select(any(..; .type == "dog")), .plane[] | select(any(..; .type == "dog")) )
匹配type == "lion"的语句
del( .car[] | select(any(..; .type == "lion")), .boat[] | select(any(..; .type == "lion")), .plane[] | select(any(..; .type == "lion")) )
通用化单条语句(通过变量指定目标type)
--arg target "dog" 'del( .car[] | select(any(..; .type == $target)), .boat[] | select(any(..; .type == $target)), .plane[] | select(any(..; .type == $target)) )'
原理说明
.car[]、.boat[]、.plane[]分别定位到三个顶级对象的直接子节点;any(..; .type == $target)递归遍历当前节点的所有后代(包括自身),判断是否存在符合条件的type值;del()只删除被选中的直接子节点,保留car、boat、plane本身及其他未匹配的子节点,完美适配不同嵌套深度的场景。
内容的提问来源于stack exchange,提问作者art vanderlay
相关产品推荐
相关产品推荐

