bash 管道与这里的字符串

bash pipe vs here-string

我认为这些命令在 bash 中是等效的,但它们产生不同的输出。 你能帮我理解为什么吗?

$ echo "SEBA" | wc
      1       1       5
$ wc <<< "SEBA"
1 1 5

运行 在

这里有一些测试:

$ echo "SEBA" | wc | hexdump 
0000000 2020 2020 2020 2031 2020 2020 2020 2031
0000010 2020 2020 2020 0a35                    
0000018
$ wc <<< "SEBA" | hexdump 
0000000 2031 2031 0a35                         
0000006
$ echo "SEBA" | hexdump 
0000000 4553 4142 000a                         
0000005
$ hexdump <<< "SEBA"
0000000 4553 4142 000a                         
0000005

当 GNU wc 从文件中获取所有输入时,它使用 stat()(或 fstat() 用于 stdin)获取所有文件的大小人物。由此它可以确定每个输出字段所需的最大位数,并且只使用那么多位数。

当任何输入是管道时,无法提前确定其大小。该输入默认为 7 位数字。

这里的字符串是通过将字符串复制到临时文件并将标准输入重定向到该文件来实现的,因此这种情况下可以使用优化的字段大小。但是来自 echo 的管道不允许这样做,所以它得到 7 位数字的字段。

查看 GNU coreutils 源代码中的函数 get_input_fstatus and compute_number_width

如评论中所述,bash 5.1 不对小的 here-strings 或 here-documents 使用临时的,它使用管道。 “小”可能不是很小,是管道缓冲区大小。如 How big is the pipe buffer? 所述,在 Mac OS X 上默认为 16K,在 Linux 上默认为 64K。所以你不应该在 bash 版本之间移植依赖于这种行为。