jq递归下降查询:如何匹配任意子键值中的子串并避免错误?
在jq中通过递归下降查找任意子键值包含指定子串的方法
问题根源
你之前的命令报错,是因为..会递归遍历JSON结构里的所有节点,包括数组、null、数字这些非对象/非字符串类型。当select(.a?|contains("hi"))遇到非对象节点时,.a?会返回null,而contains()不支持null和字符串做包含判断,直接触发类型错误。
解决方案
根据你的需求(匹配任意键的子串),分三种场景给出命令:
1. 直接获取所有包含指定子串的字符串值
如果只需要提取符合条件的字符串内容,用strings过滤出所有字符串节点,再筛选子串:
echo '[[{"a":"hi there","b":{"c":"hi again"}}]]' | jq '.. | strings | select(contains("hi"))'
输出:
"hi there" "hi again"
2. 获取包含目标子串的键值对(带键名)
如果需要保留键名和对应值,先过滤对象,转成键值对条目后筛选:
echo '[[{"a":"hi there","b":{"c":"hi again", "d":123}}]]' | jq '.. | objects | to_entries[] | select(.value | type == "string" and contains("hi"))'
输出:
{ "key": "a", "value": "hi there" } { "key": "c", "value": "hi again" }
3. 获取包含至少一个符合条件值的整个对象
如果需要保留包含目标子串的完整对象(比如原命令返回的对象结构),用any()检查对象内是否有符合条件的值:
echo '[[{"a":"hi there","b":{"c":"hi again"}}]]' | jq '.. | objects | select(any(.[]; type == "string" and contains("hi")))'
输出:
{ "a": "hi there", "b": { "c": "hi again" } } { "c": "hi again" }
关键语法说明
..:递归遍历JSON的所有层级节点objects:仅保留对象类型节点,过滤数组、字符串、null等避免报错strings:仅保留字符串类型节点to_entries[]:将对象转换为{"key": "...", "value": "..."}的键值对数组并展开any(.[]; 条件):检查对象的任意值是否满足指定条件type == "string":额外过滤字符串类型,避免数字、布尔值等非字符串触发contains()错误
内容的提问来源于stack exchange,提问作者js2010
相关产品推荐
相关产品推荐

