sed与while read读取行的差异:为何jq处理结果不同?
问题与代码示例
$ cat inputfile| while read i ;do echo ${#i}; done 12550 12972 13035 ... snip 0 $ for i in {1..21} ; do sed -n "$i"p inputfile |wc -c ; done 13226 13680 13759 ... snip 1
输入文件由21个拼接的JSON对象组成。尝试将每行内容传入jq工具时,第一种while read循环方式会报错,第二种sed循环方式可正常运行,两种循环输出均为21行,请问二者差异是什么?
差异解析
1. while read i的行为缺陷
read命令默认是为处理文本行设计的,会做这些破坏性修改:
- 自动丢弃行尾的换行符,所以
${#i}的长度不包含换行符对应的字节; - 会解析行内的反斜杠转义字符(比如把JSON里的
\n当成换行而非原始字符串); - 会截断行首/行尾的空白符,甚至合并连续空白。
你的JSON对象里必然包含换行、反斜杠或者特殊空白结构,read读取时直接破坏了JSON的语法结构,传给jq自然会解析失败。最后输出的0也说明有行被read误读成空内容——因为JSON内部的换行被错误处理后,导致read提前结束读取。
2. sed -n "$i"p的可靠之处
sed是按文件物理行来读取的,它会原封不动地保留该行所有原始内容:
- 包含行尾的换行符,所以
wc -c的结果比${#i}多1字节(换行符的大小); - 不会处理任何转义字符,也不会修改空白结构;
- 完全保留JSON的原始格式,传给jq时能正常解析。
简单总结:read会“加工”内容,sed只做“原样读取”,这就是前者报错后者正常的核心原因。
内容的提问来源于stack exchange,提问作者chx
相关产品推荐
相关产品推荐

