为什么`seq 100 | ( head -n1; tail -n1 )` 在 Mac OSX 上工作?
Why doesn't `seq 100 | ( head -n1; tail -n1 )` work on Mac OSX?
下面的命令应该打印seq 100
的第一行和最后一行,但它只打印第一行:
seq 100 | (head -n1 ; tail -n1)
1
它确实适用于更大的序列,例如 10,000:
seq 10000 | (head -n1 ; tail -n1)
1
10000
更新
我选择了@John1024 的答案,因为我的问题是为什么 不起作用,他提供了一个可接受的答案。
此外,应该显然只是我的意见..现实是head
不是这样工作的...它可能会消耗更多stdin 比我想要的要多,并且不为 tail
.
留下任何东西
当然,首先提示这个问题的问题是试图读取文件的第一行和最后n行。这是我基于 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 的 sed
:sed -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
没有自动打印模式 space
-e'1,9{p;b}'
打印前 9 行
-e'10{x;s/$/--/;x;G;p;b}'
打印第 10 行并附加 '--' 分隔符
-e':a;$p;N;21,$D;ba'
打印最后 10 行
我在 Linux 上看到 GNU head
和 tail
的相同行为。
这取决于输入 head -n1
在退出前消耗了多少。如果 head
在退出之前读取了所有标准输入,那么 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
没有任何可读取的内容。对于产生超过 8kB 的 seq 10000
,head
将不会读取管道中的所有数据。它留下的数据将可用于 tail
.
正如 Charles Duffy 指出的那样,此行为的细节完全取决于实现,并且在任何软件升级后,它可能会发生变化。
下面的命令应该打印seq 100
的第一行和最后一行,但它只打印第一行:
seq 100 | (head -n1 ; tail -n1)
1
它确实适用于更大的序列,例如 10,000:
seq 10000 | (head -n1 ; tail -n1)
1
10000
更新
我选择了@John1024 的答案,因为我的问题是为什么 不起作用,他提供了一个可接受的答案。
此外,应该显然只是我的意见..现实是head
不是这样工作的...它可能会消耗更多stdin 比我想要的要多,并且不为 tail
.
当然,首先提示这个问题的问题是试图读取文件的第一行和最后n行。这是我基于 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 的 sed
:sed -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
没有自动打印模式 space
-e'1,9{p;b}'
打印前 9 行
-e'10{x;s/$/--/;x;G;p;b}'
打印第 10 行并附加 '--' 分隔符
-e':a;$p;N;21,$D;ba'
打印最后 10 行
我在 Linux 上看到 GNU head
和 tail
的相同行为。
这取决于输入 head -n1
在退出前消耗了多少。如果 head
在退出之前读取了所有标准输入,那么 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
没有任何可读取的内容。对于产生超过 8kB 的 seq 10000
,head
将不会读取管道中的所有数据。它留下的数据将可用于 tail
.
正如 Charles Duffy 指出的那样,此行为的细节完全取决于实现,并且在任何软件升级后,它可能会发生变化。