如果您希望对方赢得这一点,您可以轻松做到(假设我们使用相同的实现tee
,因为具体的排序是实现定义的而不是标准化的):
# note that this uses automatic FD allocation support added in bash 4.1
( exec {orig_stdout}>&1; { tee >(cat >&$orig_stdout) | cat -n; } <<<$'a\nb\nc' )
简而言之:(tee
由 GNU coreutils 8.2.2 实现)写入每个块——而不是每一行;POSIX 规范tee
明确禁止面向行的输出缓冲——首先到其标准输出,然后从左到右依次到每个参数。
您可以在实现中看到:
/* Move all the names 'up' one in the argv array to make room for
the entry for standard output. This writes into argv[argc]. */
for (i = nfiles; i >= 1; i--)
files[i] = files[i - 1];
...然后使用 in 中的数组条目构建一个descriptors
1:1 的数组映射files
,并依次写入每个:
/* Write to all NFILES + 1 descriptors.
Standard output is the first one. */
for (i = 0; i <= nfiles; i++)
if (descriptors[i]
&& fwrite (buffer, bytes_read, 1, descriptors[i]) != 1)
为了解释为什么这将以一致的行为而不是竞争的方式实现—— tee 的 POSIX 规范要求它不缓冲输入。因此,必须在对每个描述符的写入之间保持顺序(当然,在该点之后,如果任何管道中的项目进行自身缓冲,顺序可能会丢失)。
现在:这并不是说tee
在继续下一个之前将完整的输入复制到每个位置。相反, tee 以BUFSIZ
每个字节块的形式工作,其中BUFSIZ
特定于操作系统的常量保证不少于 256 字节,并且在现代(非嵌入式)Linux 上经常在 8K 附近。因此,如果您使用大得多的输入,您会看到交错,正如您所期望的那样......但由于上述原因,顺序一致。