Linux 尾部反转/打印除最后 n 行之外的所有内容?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11834899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Tail inverse / printing everything except the last n lines?
提问by Tossrock
Is there a (POSIX command line) way to print all of a file EXCEPT the last n lines? Use case being, I will have multiple files of unknown size, all of which contain a boilerplate footer of a known size, which I want to remove. I was wondering if there is already a utility that does this before writing it myself.
是否有(POSIX 命令行)方式来打印除最后 n 行之外的所有文件?用例是,我将有多个未知大小的文件,所有这些文件都包含一个已知大小的样板页脚,我想将其删除。我想知道在自己编写之前是否已经有一个实用程序可以做到这一点。
回答by Adam B
Most versions of head(1) - GNU derived, in particular, but not BSD derived - have a feature to do this. It will show the top of the file except the end if you use a negative number for the number of lines to print.
大多数版本的 head(1) - 特别是 GNU 派生的,但不是 BSD 派生的 - 有一个功能可以做到这一点。如果您对要打印的行数使用负数,它将显示文件的顶部,但结尾除外。
Like so:
像这样:
head -n -10 textfile
回答by Confusion
The head
utility is your friend.
该head
实用程序是您的朋友。
From the man page of head
:
从手册页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
-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
回答by Keith Thompson
If the footer starts with a consistent line that doesn't appear elsewhere, you can use sed
:
如果页脚以没有出现在其他地方的一致行开头,则可以使用sed
:
sed '/FIRST_LINE_OF_FOOTER/q' filename
That prints the first line of the footer; if you want to avoid that:
打印页脚的第一行;如果你想避免这种情况:
sed -n '/FIRST_LINE_OF_FOOTER/q;p' filename
This could be more robust than counting lines if the size of the footer changes in the future. (Or it could be less robust if the first line changes.)
如果将来页脚的大小发生变化,这可能比计算行更可靠。(或者,如果第一行发生变化,它的健壮性可能会降低。)
Another option, if your system's head
command doesn't support head -n -10
, is to precompute the number of lines you want to show. The following depends on bash-specific syntax:
另一种选择是,如果您的系统head
命令不支持head -n -10
,则预先计算要显示的行数。以下取决于特定于 bash 的语法:
lines=$(wc -l < filename) ; (( lines -= 10 )) ; head -$lines filename
Note that the head -NUMBER
syntax is supported by some versions of head
for backward compatibility; POSIX only permits the head -n NUMBER
form. POSIX also only permits the argument to -n
to be a positive decimal integer; head -n 0
isn't necessarily a no-op.
请注意,为了向后兼容head -NUMBER
,某些版本支持该语法head
;POSIX 只允许head -n NUMBER
表单。POSIX 也只允许参数-n
是一个正十进制整数;head -n 0
不一定是空操作。
A POSIX-compliant solution is:
符合 POSIX 的解决方案是:
lines=$(wc -l < filename) ; lines=$(($lines - 10)) ; head -n $lines filename
If you need to deal with ancient pre-POSIX shells, you might consider this:
如果您需要处理古老的 pre-POSIX shell,您可以考虑:
lines=`wc -l < filename` ; lines=`expr $lines - 10` ; head -n $lines filename
Any of these might do odd things if a file is 10 or fewer lines long.
如果文件只有 10 行或更少的行,其中任何一个都可能会做一些奇怪的事情。
回答by geirha
There's no standard commands to do that, but you can use awk or sed to fill a buffer of Nlines, and print from the head once it's full. E.g. with awk:
没有标准命令可以做到这一点,但您可以使用 awk 或 sed 来填充N行的缓冲区,并在满后从头打印。例如使用 awk:
awk -v n=5 '{if(NR>n) print a[NR%n]; a[NR%n]=tail -r file.txt | tail +NUM | tail -r
}' file
回答by user9645
Probably less efficient than the "wc" + "do the math" + "tail" method, but easier to look at:
可能比“wc”+“do the math”+“tail”方法效率低,但更容易看:
cat <filename> | head -n -10 # Everything except last 10 lines of a file
cat <filename> | tail -n +10 # Everything except 1st 10 lines of a file
Where NUM
is one more than the number of ending lines you want to remove, e.g. +11 will print all but the last 10 lines. This works on BSD which does not support the head -n -NUM
syntax.
哪里NUM
比要删除的结束行数多 1,例如 +11 将打印除最后 10 行之外的所有行。这适用于不支持head -n -NUM
语法的BSD 。
回答by user2836704
It is simple. You have to add + to the number of lines that you wanted to avoid.
很简单。您必须将 + 添加到要避免的行数。
This example gives to you all the lines except the first 9
此示例为您提供了除前 9 行之外的所有行
tail -n +10 inputfile
tail -n +10 输入文件
(yes, not the first 10...because it counts different...if you want 10, just type tail -n 11 inputfile)
(是的,不是前 10 个……因为它的计数不同……如果你想要 10 个,只需输入 tail -n 11 inputfile)
回答by Siva Mandadi
回答by Jason Arthur Taylor
tac file.txt | tail +[n+1] | tac
tac 文件.txt | 尾 +[n+1] | 战术
This answer is similar to user9645's, but it avoids the tail -r command, which is also not a valid option many systems. See, e.g., https://ubuntuforums.org/showthread.php?t=1346596&s=4246c451162feff4e519ef2f5cb1a45f&p=8444785#post8444785for an example.
这个答案类似于 user9645 的,但它避免了 tail -r 命令,这在许多系统中也不是有效选项。例如,参见https://ubuntuforums.org/showthread.php?t=1346596&s=4246c451162feff4e519ef2f5cb1a45f&p=8444785#post8444785。
Note that the +1 (in the brackets) was needed on the system I tried it on to test, but it may not be required on your system. So, to remove the last line, I had to put 2 in the brackets. This is probably related to the fact that you need to have the last line ending with regular line feed character(s). This, arguably, makes the last line a blank line. If you don't do that, then the tac command will combine the last two lines, so removing the "last" line (or the first to the tail command) will actually remove the last two lines.
请注意,在我尝试测试的系统上需要 +1(在括号中),但在您的系统上可能不需要。因此,要删除最后一行,我必须将 2 放在括号中。这可能与最后一行需要以常规换行符结尾的事实有关。可以说,这使最后一行成为空行。如果您不这样做,那么 tac 命令将合并最后两行,因此删除“最后”行(或 tail 命令的第一行)实际上将删除最后两行。
My answer should also be the fastest solution of those listed to date for systems lacking the improved version of head. So, I think it is both the most robust and the fastest of all the answers listed.
对于缺乏改进版 head 的系统,我的答案也应该是迄今为止列出的最快的解决方案。所以,我认为它是列出的所有答案中最强大和最快的。