slurp、null输入与inputs过滤器的jq命令差异解析
问题背景
给定输入JSON文档:
{"a":1} {"b":2} {"c":3,"d":4}
以下jq程序输出看起来完全相同,它们是否存在差异?
jq '[., inputs] | map(to_entries[].value)'jq -n '[inputs] | map(to_entries[].value)'jq -s 'map(to_entries[].value)'
换言之,以下简化调用的效果似乎一致:
jq '[.,inputs]'jq -n '[inputs]'jq -s '.'
需要明确:
- 它们的核心区别是什么?
- 有没有只有某一种方式能生效的场景?
- 旧版本jq是否不支持其中部分写法?
- 是否存在性能差异?
- 还是仅仅是可读性和个人偏好的区别?
附加问题
以下程序是否也存在上述类似的等价情况?
4. jq '., inputs | to_entries[].value'
5. jq -n 'inputs | to_entries[].value'
6. jq -s '.[] | to_entries[].value'
7. jq 'to_entries[].value'
核心差异解析
先拆解三个简化调用的本质:
jq '[.,inputs]':默认模式下,jq会先把第一个输入JSON作为初始的.,再用inputs读取剩下的所有输入,最后把初始值和inputs的结果拼成数组。jq -n '[inputs]':-n参数让jq不加载任何初始输入,直接用inputs读取全部输入并拼成数组。jq -s '.':-s(slurp)参数会把所有输入JSON一次性读入内存,直接拼成一个数组返回。
场景差异
- 当没有输入时:
jq '[.,inputs]'会输出[null](因为初始.没有输入源,默认是null),而jq -n '[inputs]'和jq -s '.'会输出[]空数组,这是最直观的区别。 - 如果需要先单独处理第一个输入,再合并后续输入,
[.,inputs]的写法可以拆分步骤(比如先对.做过滤/转换,再和inputs合并),另外两种写法做不到这种拆分。
版本支持
inputs是jq 1.5版本才引入的特性,1.5之前的旧版本只能用-s参数。如果要兼容老环境,-s是更稳妥的选择。
性能差异
-s参数是一次性把所有输入读入内存,处理超大体积的输入流(比如几G的JSON文件)时,会占用大量内存,甚至触发内存不足。[.,inputs]和-n '[inputs]'是流式处理,逐个读取输入,内存占用极低,适合处理大文件或持续的输入流。
可读性与偏好
-s '.'写法最简洁,一眼就能看出来是“把所有输入拼成数组”;[.,inputs]和-n '[inputs]'更显式,能明确体现“处理输入流”的逻辑,可读性因人而异。
附加问题解析
这四个程序在常规输入下输出确实一致,但同样存在场景和特性差异:
jq '., inputs | to_entries[].value':默认模式下先输出第一个输入的value,再输出后续所有输入的value;无输入时会报错(因为null没有to_entries方法)。jq -n 'inputs | to_entries[].value':无初始输入,直接输出所有输入的value;无输入时无输出。jq -s '.[] | to_entries[].value':先把所有输入拼成数组,再逐个展开输出value;无输入时无输出,但处理大文件时会有内存压力。jq 'to_entries[].value':默认模式下逐个处理每个输入,输出每个输入的value;无输入时无输出,纯流式处理,内存占用最低,旧版本jq也支持。
核心差异总结:
- 无输入场景:第1种会报错,其他三种无输出;
- 大文件处理:第4种和第2种内存占用最低,第3种内存压力最大;
- 版本兼容:第1、2种依赖jq 1.5+,第3、4种在旧版本也能正常运行。
内容的提问来源于stack exchange,提问作者knittl
相关产品推荐
相关产品推荐

