三通>(Cat -N) < tmpfile 在重复之前完全打印 TMP 文件



tmpfile 包含以下内容:

a
b
c
d

问题标题中命令的输出如下:

[me@localhost somedir]$ tee >(cat -n) < tmpfile    
a
b
c
d
[me@localhost somedir]$      1  a
     2  b
     3  c
     4  d

由于 t 恤和 cat 是通过命名管道连接的,我希望 cat 在 t 形打印下一行之前完成向终端发送输出。像这样:

[me@localhost somedir]$ tee >(cat -n) < tmpfile    
a
1  a
b
2  b
c
3  c
d
4  d
[me@localhost somedir]$     

有人可以解释一下这里发生了什么吗?我考虑了竞争条件的可能性,其中发球台刚刚获胜,但大小等于几个KB的文件也会发生这种情况。我觉得这里还有更多的东西。

谢谢。

如果你想让

另一方赢得这个,你可以很容易地做到这一点(假设我们使用相同的tee实现,因为特定的排序是实现定义的而不是标准化的):

# note that this uses automatic FD allocation support added in bash 4.1
( exec {orig_stdout}>&1; { tee >(cat >&$orig_stdout) | cat -n; } <<<$'anbnc' )

简而言之:tee(由GNU coreutils 8.2.2实现)写入每个块 - 而不是每一行;tee的POSIX规范明确禁止面向行的输出缓冲 - 首先到它的stdout,然后依次到每个参数,从左到右。

您可以在实现中看到:

/* 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];

。然后用 files 中的数组条目 1:1 构建一个 descriptors 数组映射,并依次写入每个数组:

/* 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 附近。因此,如果您使用明显更大的输入,您将看到交错,正如您所期望的那样......但出于上述原因,顺序一致。

最新更新