头部是否会消耗stdin中的其他字符?

mar*_*ril 12 linux bash shell

当我执行以下head命令时:

yes 123456789 | ( head -n 1; head -n 1 )
Run Code Online (Sandbox Code Playgroud)

我明白了:

123456789
3456789
Run Code Online (Sandbox Code Playgroud)

虽然我期望:

123456789
123456789
Run Code Online (Sandbox Code Playgroud)

当我执行时,它也让我感到困惑:

echo -e "123456789\n123456789\n123456789\n123456789\n123456789\n" | \
( head -n 1; head -n 1 )
Run Code Online (Sandbox Code Playgroud)

我明白了:

123456789
Run Code Online (Sandbox Code Playgroud)

代替:

123456789
123456789
Run Code Online (Sandbox Code Playgroud)

我猜有些东西我不明白.你知道我为什么会这样做吗?

Kar*_*ath 7

输入和输出是完全不同的野兽.手册head告诉您预期的输出是什么,但它没有告诉您有关如何处理输入的任何信息.

所以简短的回答是:你依赖于无证件的东西.

现在,如果您有兴趣知道幕后发生了什么,可以添加一些跟踪

| ( strace head -n 1; tail )
Run Code Online (Sandbox Code Playgroud)

在你的第二个例子中:注意:对于strace格式抱歉,我现在正在使用cygwin.:

[...]
 24   35374 [main] head 1784 read: 51 = read(0, 0x22C700, 1024)
Run Code Online (Sandbox Code Playgroud)

第一个head进程是通过读取一个大块(1024字节)来尝试读取输入,然后可能在缓冲区中查找换行符.至少,这就是我实现它的方式.如您所见,它处理了所有51个字符,因此下一个进程没有任何剩余.

在你的第一个例子中:这里的主要区别在于我们有一个无穷无尽的输入,所以即使第一个head将读取一个大块,还有第二个进程留下的输入.边界将是任意的,它取决于块大小,头的实现,如何实现fread(缓冲IO)等等.例如,在我的系统上,这是输出:

123456789
56789
Run Code Online (Sandbox Code Playgroud)


Pet*_*ake 7

是的,head绝对是读一行以上.它将进行缓冲I/O. 从文件读取,它似乎是按行读取,但是从管道读取,它一次读取512字节.这与你所看到的一致.的3456789可能不是2号线,但第52.要试验这个,请使用可以分辨线而不是分开的东西yes.cat somefile |很好地工作.