尾巴的对面:除最后n行外的所有行


36

如何使用Unix命令行过滤器丢弃文件的最后n行?

这与tail:的相反:tail丢弃前n行,但其余部分通过管道传输,但是我希望命令通过管道传输最后n行以外的所有内容。

不幸的是,我还没有找到类似的东西-也head没有帮助。编辑:至少在Solaris中,它不接受否定参数。

更新:我对一种适用于大文件(即日志文件)的解决方案最感兴趣,在该解决方案中,您可能希望检查最后一分钟发生的情况。


仅供参考,当使用head时:通过使用-n选项在数字前放置'-',它将打印每个文件的所有行,但不打印最后N行,如下所示,
G Koe 2013年

Answers:


38

如果您有GNU head,则可以使用

head -n -5 file.txt

打印的最后5行以外的所有内容file.txt

如果head -n不带否定参数,请尝试

head -n $(( $(wc -l file.txt | awk '{print $1}') - 5 )) file.txt

11
(并祈祷file.txt至少长六行...)
CVn 2013年

1
遗憾的是,此非GNU版本也无法与流一起使用
-Armand

1
@MichaelKjörling至少在ubuntu上,这不是问题。如果文件的行数少于中指定的行数head,则返回空输出,且无错误。
Alphaaa

如果我没记错的话,头-n 5将打印前5行,但不是最后5行...
pypmannetjies

8
head file.txt               # first 10 lines
tail file.txt               # last 10 lines
head -n 20 file.txt         # first 20 lines
tail -n 20 file.txt         # last 20 lines
head -20 file.txt           # first 20 lines
tail -20 file.txt           # last 20 lines
head -n -5 file.txt         # all lines except the 5 last
tail -n +5 file.txt         # all lines except the 4 first, starts at line 5

1
在接受的答案中未回答的内容是什么?另外,与您的其他答案一样,对您的答案进行几行解释会大大改善它。
music2myear

1
很好的摘要
ruanhao

5

这是删除最后一行的简单方法,该方法适用于BSD等。

sed '$d' input.txt

该表达式显示为“在最后一行,将其删除”。其他行将被打印,因为这是sed默认行为。

您可以将它们链接在一起以删除多行

sed '$d' input.txt | sed '$d' | sed '$d'

诚然,这有点笨拙,但只扫描文件一次。

您还可以查看此内容,以获得更多答案: https //stackoverflow.com/questions/13380607/how-to-use-sed-to-remove-last-n-lines-of-a-file

这是我那里最喜欢的一种改编的单线纸:

N=10
sed -n -e ':a' -e "1,$N!{P;N;D;};N;ba"

我很高兴地破译了那个,并且我也希望你也能这样做(:它在N扫描时确实缓冲行,但否则效率很高。


3

我很好奇您为什么认为head没有选择:

~$ man head
...
-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 -20 yourfile.txt

5
注意,这仅适用于GNU head。BSD head没有这个选项,那么这个答案会不会在Solaris或其它Unix系统没有GNU的coreutils工作。OP还专门用Unix和Unix-Utils标记了这一点。
slhck 2013年

2
@slhck更不用说OP提到这是针对Solaris的事实。
一个CVN

不幸的是有人删除了我提到的Solaris。但是无论如何,我应该提到head版本不支持该功能。
汉斯·彼得·斯托尔2013年

1
不好意思 没有注意到Solaris,也不知道head的各种版本。
Anders R. Bystrup 2013年

1
@hstoerr Solaris现在已加入您的标记中:)
slhck

0

如果tail -n不接受否定论点的另一种方法是

tac file.txt | tail -n +6 | tac

这将删除最后5行


谢谢!到目前为止,还没有人提出这个想法。不幸的是,对于我想到的这个用例来说,这是非常低效的:如果是一个大文件,它不仅会像其他解决方案一样被完全读取一次或多次,而且可能还会写入如果tac不能容纳到内存中,则通过tac将其复制到临时文件。
汉斯·彼得·斯托尔

@ Hans-Peter非常正确。决定为其编写python3脚本。试试这个github.com/atw31337/donkey。我建议使用输出选项。它们的运行比使用重定向快得多。
atw31337 21:06

写得好!但是,它确实会两次读取文件,如果您缓冲了最后n行,这实际上不是必需的,这对于大文件是个问题。就个人而言,我不再需要它了,但是如果您有改进它的乐趣,而其他人则需要它……毕竟,在这个问题上有一些喜欢和喜欢的人。
汉斯·彼得·斯托尔

@汉斯·彼得 缓冲区大小取决于要删除的行数。如果需要从文件中删除大量行,则可能会出现问题。为了避免与内存相关的问题,我重写了脚本,以使用具有高n值的行计数方法和具有低n值的缓冲方法。但是,在很大的文件上对其进行测试后,原始的行数计算方法仍然更快。似乎缓冲区管理的开销超过了行数的开销...或者我只是缺少了一些东西。
atw31337

很好,但是对于BSD变体的Mac OS X,默认情况下没有tac命令。:(这种失败的使用情况。
ingyhere
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.