如何在jq过滤中途将独立JSON对象转换为数组(slurp操作)
解决每行JSON日志筛选后转数组并执行数组操作的问题
问题回顾
你有每行一个JSON对象的Elastic日志,需要筛选出level != "INFO"的条目,将其转换为数组后执行map(.message) | unique这类数组操作,但直接组合筛选和数组操作会报错,用inputs的尝试也未达到预期。
可行解决方案
方案1:先 slurping 转数组再筛选(最直观)
直接用-s(slurp)选项将所有单行JSON合并为数组,之后先筛选再处理:
jq -s 'map(select(.level != "INFO")) | map(.message) | unique' my_log_file.txt
执行逻辑:
-s把所有日志行打包成一个JSON数组map(select(.level != "INFO"))过滤掉INFO级别的条目- 后续的
map(.message) | unique提取所有message并去重
方案2:用inputs结合-n选项(更灵活)
如果不想一开始就slurp所有数据,可以用-n选项让jq不自动读取第一个输入,而是通过inputs获取所有行,在收集时直接筛选:
jq -n '[inputs | select(.level != "INFO")] | map(.message) | unique' my_log_file.txt
执行逻辑:
-n启动jq但不读取初始输入inputs遍历所有日志行的JSON对象- 对每个对象执行
select(.level != "INFO")筛选,再用[]把所有符合条件的对象包裹成数组 - 后续执行数组操作提取message并去重
如果只需要将筛选后的结果转为数组(不做后续提取去重),执行这条命令即可:
jq -n '[inputs | select(.level != "INFO")]' my_log_file.txt
之前尝试失败的原因
- 直接执行
jq 'select(."level" != "INFO") | map(.message) | unique'报错:map是数组操作,而select输出的是单个JSON对象(而非数组),jq会尝试把单个对象的键当作字符串索引,导致"Cannot index string with string 'message'"错误。 - 执行
jq 'select(."level" != "INFO") | [inputs]'无效:select只处理了第一行输入,inputs会读取剩余所有行且未应用筛选条件,最终结果是第一行符合条件的对象加上所有剩余对象的数组,完全不符合需求。
内容的提问来源于stack exchange,提问作者Noumenon
相关产品推荐
相关产品推荐

