Linux bash下paste命令双流逐行交错输出行为是否有规范保障?
paste -d "\n" 双流逐行交错的行为可靠性说明 核心疑问
在bash shell中使用paste设置分隔符为\n,对两个并行命令的输出做逐行交替拼接,实现自定义格式的十六进制转储(奇数行来自第一个命令的ASCII处理结果,偶数行来自第二个命令的十六进制字节结果)。
实际运行中代码功能正常,但存在两点顾虑:
- 本地OS X、Ubuntu 18.04的手册页未明确说明
paste处理双流的逻辑,不确定逐行交替的行为是否有规范强制保障 - 如果两个子命令运行速度不一致,会不会出现快的一方连续输出多行、等慢的一方积累足够行后再继续交替的情况,破坏预设的输出格式
已知cat处理双输入流的行为无规范保障:默认会先完整输出第一个流的全部内容,再输出第二个流的内容,仅靠系统缓冲区边界的随机触发才会出现偶发的交错。因此需要明确paste的行为是否和cat一样属于未定义的偶然表现。
规范层面的可靠保障
paste的逐行交替行为是POSIX标准强制规定的,和cat的随机交错有本质区别:
paste的核心工作逻辑是行级对齐拼接:逐行读取所有输入流,将所有输入流中相同行号的内容,按指定分隔符拼接为单条输出行。- 执行过程中,
paste会对每个输入流做行级阻塞等待:必须拿到所有输入流对应行号的完整内容(直到读取到换行符或者流结束标记),才会生成对应的输出行。
这种阻塞等待机制从根源上杜绝了单流连续输出的问题:哪怕其中一个子命令输出速度极慢,paste也只会卡在等待状态,不会拿快输出流的后续行补位凑数。
逻辑差异对比:
cat是无行感知的流复制工具,按顺序读满系统缓冲区就直接写输出,完全不关心内容的行边界,因此会出现先吐完单一流全部内容的表现paste是强行感知的处理工具,必须按行号对齐所有输入,天生就满足逐行交替的设计要求
例外场景说明
唯一可能打破纯交替逻辑的情况是:某一个输入流提前结束输出(即内容已全部发送完毕)。此时按照规范,paste会把已结束的流对应行位置替换为空串,继续处理另一个流的剩余内容,不会打乱已完成行的交替顺序。
对应十六进制转储实现参考
基于上述可靠逻辑,这些代码的交错输出效果不会随机失效:
基础可用版本
# Version 1 paste -d "\n" <( cat "${largeFile}" | LC_CTYPE=C tr -c '[:print:]' '.' | sed -E $'s/.{30}/&\\\n/g' | sed 's/./& /g' ) <( xxd -p "${largeFile}" | sed 's/../& /g' )
输出效果为ASCII行与十六进制行严格交替:
G I F 8 9 a . . q . w . . ! . 3 C r e a t e d w i t h t 47 49 46 38 39 61 c7 01 71 00 77 ff 00 21 fe 33 43 72 65 61 74 65 64 20 77 69 74 68 20 74 ...
大文件优化版本
减少多进程sed的调用开销,使用fold做行拆分,处理大文件时性能更高:
# Version 2 paste -d "\n" <( cat "${largeFile}" | LC_CTYPE=C tr -c '[[:print:]]' '.' | fold -bw 1 | tr "\n" " " | fold -bw 2 | tr "\n" " " | fold -bw 90 ) <( xxd -p "${largeFile}" | fold -bw2 | tr -s "\n" " " | fold -bw 90 )
原生工具替代实现
不依赖paste与多管道组合,直接用hexdump的格式化参数实现同等的行交替效果:
formatAscii=\ '/0 "%010_ad |\t" '\ '30/1 " %_p " '\ '"\n"' formatHex=\ '/0 "%010_ad |\t" '\ '30/1 "%02x " '\ '"\n"' hexdump -v -e "${formatAscii}" -e "${formatHex}" "${largeFile}"
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

