从“猫头”和“尾巴”的猫输出中读取“第一行和最后一行”时的奇怪结果

时间:2017-08-13 02:46:03

标签: bash tail head

Bash版本4.4.7。

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

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

但是,对于大文件(我不知道它有多大,但文件大约有几千行),这个命令运行良好,但对于小文件,例如:

11111111
22222222
33333333
44444444

命令输出只是第一行:

11111111

使用awk的另一个命令适用于这两个文件:

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

2 个答案:

答案 0 :(得分:3)

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

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

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

这里发生了什么?我们的管道工作如下:

  • 向stdout发送行(在本例中为数字,但与您的cat示例没有区别);
  • 阅读标准我们:

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

但是,默认情况下,head 不是逐行读取文件,甚至是逐字符读取文件,直到找到换行符,而是以块的形式读取文件(a缓冲读)。例如,该块可能是2048字节。

所以我们的管道真的是:

  • 向stdout发送行(在本例中为数字,但与您的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 :(得分: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; }