2017-08-13 47 views
0

Bash版本4.4.7。奇怪的结果,同时执行阅读'头'和'尾'Cat输出'第一和最后一行'

tutorial,以获得第一和文件的最后一行:

cat txt_file | (head -n1 && tail -n1) 

但是,对于大文件(我不知道有多大,这将工作,但与文件有关千行)该命令运行良好,但对于小的文件,例如:

11111111 
22222222 
33333333 
44444444 

命令的输出大约是仅在第一行:

11111111 

其他命令,用awk,作品有两个文件:

awk 'NR==1; END{print}' 
+2

对我来说,这似乎并不奇怪......除非输入大于任何缓冲区大小,否则不太可能出现“head && tail”。 – donkopotamus

+0

@donkopotamus我不知道,你能解释一下吗?以及如何让这个例子的头部,尾部工作!谢谢! – duqu

+0

你能解释一下它是如何工作的吗?每个命令一次加载一个缓冲区,尝试用该缓冲区终止,然后将剩余的缓冲区交给下一个命令?通常缓冲区大小有多大?或者我怎么能找到这个结果? – rubystallion

回答

3

你的“问题”此刻实际上并没有提出一个问题,它只是一个观察。然而,解释你的观察。考虑的输出之间的差别:

$ seq 10 | (head -1 && tail -1) 
1 

$ seq 1000 | (head -1 && tail -1) 
1 
1000 

这到底是怎么回事?我们的流水线工作如下:

  • 发送线(在这种情况下与数字,但其对你的cat例如没有不同)到标准输出;
  • 阅读标准输出,我们有:

    • 首先,head ......它将打印的第一行,然后结束;
    • 接下来,一个tail ...它将开始头已运行并打印最后一行。

然而,在默认情况下,head不读通过字符行,甚至字符文件中的行,直到它找到一个换行符,而不是它的读取数据块文件(缓冲读) 。例如,该块可能是2048个字节。

因此,我们的管道是真的:

  • 发送线(在这种情况下,与电话号码,但它没有什么不同您cat例子)到标准输出;
  • 阅读标准输出,我们有:

    • 首先,head ......它会读取从标准输入第一2KB,打印的第一行,然后结束;
    • 接下来,一个tail ...它会读取其后的数据之后的第一个2K,因为它从来没有看到它

如果你的目标是只产生了第一个命令的输出(您cat)一次,那么你可以使用tee,这样或许还有:

$ seq 10 | tee >(tail -1) | head -2 

也要注意, Linux,你可以改变缓冲的第一个命令,如:

$ stdbuf -oL seq 10 | (head -1 && tail -1) 

但这不会工作,如果你的命令其流拨弄(见stdbuf)以下太

1

尝试: SED解决方案:

sed -n '1p;$p' <(seq 1000) 

perl的解决方案:

seq 100 | perl -ne 'print if 1..1 or eof' 

只有尾巴bash的解决办法:

seq 100 | { IFS= read -r line; echo "$line"; tail -1; } 
相关问题