【发布时间】:2017-12-27 04:48:09
【问题描述】:
以下命令应该打印来自seq 100的第一行和最后一行,但它只打印第一行:
seq 100 | (head -n1 ; tail -n1)
1
它确实适用于更大的序列,例如 10,000:
seq 10000 | (head -n1 ; tail -n1)
1
10000
更新
我选择了@John1024 的答案,因为我的问题是为什么这不起作用,他提供了一个可以接受的答案。
另外,应该显然只是我的意见。现实是head 不能这样工作...它很可能消耗比我想要的更多的标准输入,并为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 没有自动打印模式空间
-e'1,9{p;b}' 打印前 9 行
-e'10{x;s/$/--/;x;G;p;b}' 打印第 10 行并附加“--”分隔符
-e':a;$p;N;21,$D;ba' 打印最后 10 行
【问题讨论】:
-
如果你想只读一行并且不消耗更多的输入,顺便说一句,你可以自己实现:
seq 100 | { read first; echo "$first"; tail -n1; }符合你的期望。 -
(顺便说一句,我对问题中的“应该”提出异议。如果你能找到一个书面保证,证明这里描述的行为会破坏,我很乐意看到它;
head符合的标准to 是here - 没有提供明显的保证:消耗了多少标准输入)。 -
您可以通过使用单个程序打印第一行和最后一行来避免这个问题,例如
seq 100 | sed -n '1p; $p'. -
@CharlesDuffy 我理解你对“应该”的立场。我已经更新了我的答案,以反映“应该”只是我的意见。
head不保证从标准输入“放回”未使用的字节这一事实是,IMO,不正确的行为,应该更新规范并修改head。 -
没有机制可以批量“放回”内容。您要么一次只读取一个字节并且使事情变得非常慢(这就是
read的shell 实现所做的,以及为什么它的性能如此糟糕),或者您读取大块并消耗比您需要的更多。