为什么没有'seq 100 | (head -n1; tail -n1)`在Mac OSX上工作?

时间:2017-12-27 04:48:10

标签: bash pipe seq

以下命令应该打印seq 100的第一行和最后一行,但它只打印第一行:

seq 100 | (head -n1 ; tail -n1)
1

它适用于较大的序列,例如10,000:

seq 10000 | (head -n1 ; tail -n1)
1
10000

更新

我已经选择了@ John1024的答案,因为我的问题是为什么没有这项工作,他提供了一个可接受的答案。

另外,应该显然只是我的观点..现实是head不会这样做...它可能会消耗更多的stdin而不是我和#39; d喜欢,并且不为tail留下任何内容。

当然,在第一个问题中提示此问题的问题是尝试读取文件的第一行和最后一行。这是我根据GNU sed提出的解决方案:

sed -ne'1,9{p;b}' -e'10{x;s/$/--/;x;G;p;b}' -e':a;$p;N;21,$D;ba'

或更紧凑

sed -ne'1,9{p;b};10{x;s/$/--/;x;G;p;b};:a;$p;N;21,$D;ba'

示例输出:

*注意在我的Mac上,使用MacPorts,GNU sed被调用为gsed。 Apple的内置sed对于分号分隔表达式很挑剔,需要多个-e个参数。这应该适用于Apple的sedsed -ne'1,9{' -e'p;b' -e'}' -e'10{' -e'x;s/$/--/;x;G;p;b' -e'}' -e':a' -e'$p;N;21,$D;ba' *

seq 100 | gsed -ne'1,9{p;b}' -e'10{x;s/$/--/;x;G;p;b}' -e':a;$p;N;21,$D;ba'

1
2
3
4
5
6
7
8
9
10
--
91
92
93
94
95
96
97
98
99
100

解释

gsed -ne'在没有自动打印模式空间的情况下调用sed

-e'1,9{p;b}'打印前9行

-e'10{x;s/$/--/;x;G;p;b}'打印第10行,附加' - '分离器

-e':a;$p;N;21,$D;ba'打印最后10行

1 个答案:

答案 0 :(得分:6)

我在Linux上看到与GNU headtail相同的行为。

取决于输入head -n1在退出前消耗的数量。如果head在退出之前读取了所有stdin,那么tail没有任何东西可以读取而tail不会产生任何输出。

观察:

$ seq 10000 | (head -n1 ; cat ) | head
1

1861
1862
1863
1864
1865
1866
1867
1868

在这里,我们可以看到head -n1消耗了前1860行。 cat命令可以看到所有剩余的输入。

为什么?观察前1860行中有多少字节:

$ seq 1860 | wc
   1860    1860    8193

合理的猜测是head -n1首先从stdin读取8kB数据,然后打印第一行,并且看到它不需要更多数据,它就会退出。 stdin的其余部分可用于任何后续过程。

因此,seq 100产生的总输出小于8kB,head读取所有标准输入并且不会留下任何tail来读取。如果seq 10000产生的密度超过8kB,head将无法读取管道中的所有数据。它留下的数据将可用于tail

正如Charles Duffy所指出的,此行为的详细信息完全取决于实现,并且在任何软件升级时,它可能会发生变化。