我的文件充满了文件号(从0开始)
$ cat in.del
0
1
2
....
有人可以解释这里发生了什么以及缓冲在管道中何处发生?据我了解,两个head's
fileno(stdin)都必须直接查看管道的读取端
$ cat in.del | ( head -n1 ; head -n1 )
0
60
以下代码与上面的代码有何不同?
$ cat in.del | ( head -n10 ; head -n10 )
0
1
...
8
9
60
1861 # O_o
1862
1863
...
1868
1869
这可以按预期工作,并且表明head
本身读取的字节数不超过其实际写入其stdout
的字节数:
$ ( head -n10 ; head -n10 ) < ./in.del
0
1
...
9
10
11
...
18
19
很显然,这与发生管道有关
更新
OS:Ubuntu 18.04.1 LTS
Bash:版本4.4.19(1)-发行版(x86_64-pc-linux-gnu)
更新2 除了@Barmar的出色答案之外,more on stdio buffering
答案 0 :(得分:4)
正在发生的事情是stdio一次从管道读取了整个缓冲区,而Linux上的缓冲区大小为8K。
然后dbleon1
从缓冲区中读取前10行,将其打印并退出。
下一个head
从最后一个中断的管道开始读取,该管道中有8K字节。它读取该行以及随后的9行。您看到的head
是60
的结尾。
在最后一种情况下按预期方式工作的原因是因为1860
在退出前一直搜索到它所打印的最后一行的末尾。寻找在管道中不起作用,因此这没有效果。但是,当head
是普通文件时,查找将起作用,并且下一个过程将从查找设置文件位置的地方开始。
我在Mac上看到的结果略有不同。它的缓冲区大小为64K,因此第二个stdin
从文件的后面开始。在退出之前,它也不会搜索到最后一个打印行的末尾,因此带有文件重定向的版本与管道相同。