什么是“head”的相反意思?我想要文件除了前N行之外的所有内容。

187

如果有一个长度未知的文本文件,例如如何读取除文件前两行以外的所有内容?我知道tail命令可以给出最后N行,但是我事先不知道N的值。

因此对于一个文件:

AAAA
BBBB
CCCC
DDDD
EEEE

我想要

CCCC
DDDD
EEEE

对于一个文件

AAAA
BBBB
CCCC

我只会得到

CCCC

这个回答解决了你的问题吗?如何使用bash/sed脚本删除文本文件的第一行? - cachius
这个问题已经在这里这里有答案了。 - cachius
9个回答

281

tail --help 给出以下内容:

  -n, --lines=K            output the last K lines, instead of the last 10;
                           or use -n +K to output lines starting with the Kth
      

为了过滤掉前2行,使用-n +3将给你你想要的输出(从第三行开始):

tail -n +3

2
奇怪的是,我的手册页面上没有列出这个选项,但它完全可以正常工作 - 谢谢! - Nicholas M T Elliott
@Nicholas:奇怪,我认为无论操作系统如何,它都应该是标准文档。我从Windows内部的Cygwin中提取了它,所以我不知道在各种Linux发行版中它是什么样子。很高兴它起作用了。 - Joe Enos
@NicholasMTElliott man7 将其列为 Joe Enos 的 manpage,因此很可能是 manpage 版本问题。 - Uli Köhler
@SteveJorgensen:我不明白你的评论指的是什么;好像也没有人建议使用head来做这件事? - ruakh
3
可能对大家都很明显,只有我不知道,但是 +K 是以 1 为起始索引的第 K 行,所以例如 tail -n +1 等同于 cat。要获取除第一行之外的所有行,您需要执行 tail -n +2 - Lucas Wiman

30

假设您使用的 tail 版本支持,您可以指定从 X 行之后开始查看。在您的情况下,您需要输入 2+1。

tail -n +3

[mdemaria@oblivion ~]$ tail -n +3 stack_overflow.txt
CCCC
DDDD
EEEE

14

使用 awk 的简单解决方案:

awk 'NR > 2 { print }' file.name

我们中有人感到困惑。问题是:“除了文件的前两行之外的所有内容”。那个命令为什么不符合要求? - janm
9
"{ print }" 是默认的操作,可以省略。 - tripleee

10

尝试使用sed 1,2d。根据需要替换数字2。


正如预期的那样工作,因为前两行后面的行数是未知的。 - kumarprd

9

tail -n +linecount filename 将从 filename 的第 linecount 行开始输出,因此 tail -n +3 filename 应该可以满足您的需求。


这在我的shell中不起作用,但是tail -n +17 filename可以。我使用bash/ubuntu LTS。 - isomorphismes
2
@iso:感谢提醒--旧版本的 tail 接受了我在原回答中使用的语法,但现在需要使用显式的 -n 选项。我已相应更新了我的回答。 - Jim Lewis

0

如果第一个样本被称为sample1.dat,那么使用以下命令:tail --lines=3 sample1.dat,它将打印从第三行到最后一行的所有行。

对于第二个样本,假设它被称为sample2.dat,则使用以下命令:tail --lines=-1 sample2.dat,它将打印最后一行...


@Jim:你的和我的有什么区别?……一样的东西……:o 我是在回答他的问题,展示如何实现他所寻求的内容,针对两个样本数据文件输入。 - t0mm13b
好的...那他为什么要求第二个样本并展示他想要的结果,而我使用了“tail --lines=-1”呢......当然你可以完全省略文件名,它仍然可以作为一个管道... 嗯 - t0mm13b
@tommie:哎呀,我说的管道忘了,可能是想到了其他实用程序。但我的观点是,对于一般情况,单个命令“tail +3 anyfile”即可得到所需结果,而“tail --lines=N”需要事先知道N才能得到所需结果。 - Jim Lewis
@tommie:但这是“tail”(尾部)...不应该是“底部向上”吗?(Ba-dum TISH!谢谢,我这周都会在这里...) - Jim Lewis

0

head 函数支持使用负数。

head --help

-n, --lines=[-]K         print the first K lines instead of the first 10;
                         with the leading '-', print all but the last
                         K lines of each file

例如,正数将打印前两行。
 head -n +2

 AAAA
 BBBB

一个负数会打印除了前两行之外的所有内容。
head -n -2

CCCC
DDDD
EEEE

请注意,与 tail 不同的是,这并不需要事先知道文件中总行数。它将排除前两行,无论有多少行。tail -n -2 中的负数同样可用于删除文件的 最后 2 行。
请注意,这使用 GNU head 版本 8.22。该功能可能在最初发布时不可用。即使是相当老的 Linux 发行版,现在也可用。

1
遗憾的是,在 Mac 上(这里使用 macOS 12.6),head 命令不接受像 head -n -2 这样的负数来跳过开头的行数(会报错“非法行数”)。然而,虽然没有文档记录,但 tail -n +3 命令加上一个加号三确实可以从第三行开始(在另一个答案中建议使用此方法)。 - Peter Cock

-1

我真的不知道如何仅从头或尾部开始完成它,但是通过使用wc -l(行计数)和bash表达式的帮助,您可以实现这一点。

tail -$(( $( wc -l $FILE | grep -Eo '[0-9]+' ) - 2 )) $FILE

希望这能帮到你。

1
这需要在运行tail之前对文件进行完整的遍历。如果文件大于内存大小,这将非常低效。它不处理少于两行的文件。它不处理wc和tail之间文件大小的变化。 - janm
2
@janm:你说得没错。其他答案更好。我感到有点尴尬。:-p - NawaMan

-1
使用 awk 获取除最后两行之外的所有行
awk 'FNR==NR{n=FNR}FNR<=n-3{print}' file file

使用awk获取除了前两行以外的所有内容

awk 'NR>2' file

或者您可以使用更多的方法

more +2 file

或者只是bash

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"

现在这个命令不符合要求。问题说“除了文件的前两行之外”,并给出了两个例子,每个例子都有一个单独的文件,在这些文件中,跳过了前两行,其余部分被发送到标准输出。但是这个命令并没有做到这一点。 - janm
是的,我误读了问题。我以为他要求除了最后两行之外的所有内容。 - ghostdog74

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接