当我执行以下head
命令时:
yes 123456789 | ( head -n 1; head -n 1 )
我明白了:
123456789
3456789
虽然我期待:
123456789
123456789
当我执行时,我也很困惑:
echo -e "123456789\n123456789\n123456789\n123456789\n123456789\n" | \
( head -n 1; head -n 1 )
我明白了:
123456789
而不是:
123456789
123456789
我想有些事我不明白。你知道我为什么会这样做吗?
答案 0 :(得分:7)
输入和输出是完全不同的野兽。 head
的手册告诉您预期的输出是什么,但它没有告诉您有关如何处理输入的任何信息。
所以简短的回答是:你依赖于无证件的东西。
现在,如果您有兴趣知道幕后发生了什么,可以添加一些跟踪
| ( strace head -n 1; tail )
在你的第二个例子中:注意:抱歉为strace格式,我现在正在使用cygwin。:
[...]
24 35374 [main] head 1784 read: 51 = read(0, 0x22C700, 1024)
第一个head
进程尝试通过读取一个大块(1024字节)来读取输入,然后可能在缓冲区中查找换行符。至少,这就是我实现它的方式。正如您所看到的,它处理了所有51个字符,因此下一个过程没有任何剩余。
在你的第一个例子中:这里的主要区别在于我们有无穷无尽的输入,所以即使第一个head
会读取一个大块,也会留下第二个进程的输入。边界将是任意的,它取决于块大小,头的实现,如何实现fread(缓冲IO)等等。例如,在我的系统上,这是输出:
123456789
56789
答案 1 :(得分:7)
是的,head
肯定会读取多行。它将进行缓冲I / O.从文件读取,它似乎是按行读取,但是从管道读取,它一次读取512字节。这与你所看到的一致。 3456789
可能不是第二行,而是第52行。要试验这一点,请使用可以区分线而不是yes
的内容。 cat somefile |
效果很好。
答案 2 :(得分:3)
(这里的答案很晚。)
虽然existing answer解释了您观察到的原因,但您可以使用变通方法来获取预期输出。
将输出管道输出到行缓冲区输出的内容:
$ yes 123456789 | { head -n 1; head -n 1; }
123456789
56789
$ yes 123456789 | grep --line-buffered . | { head -n 1; head -n 1; }
123456789
123456789
请注意,我使用了{ ... }
,即命令分组,与( ... )
不同,它不会创建子shell。
答案 3 :(得分:1)
如果你想获得
123456789
123456789
然后你需要这样的东西:
yes 123456789 | head -2
(是循环直到管道断裂,头-2给你2行)
对于第二部分,它应该遵循以获得你想要的东西:)
echo -e "123456789\n123456789\n123456789\n123456789\n123456789\n" | head -2