49

是否有(POSIX 命令行)方法可以打印除最后 n 行之外的所有文件?用例是,我将有多个未知大小的文件,所有这些文件都包含一个已知大小的样板页脚,我想删除它。我想知道在自己编写之前是否已经有一个实用程序可以执行此操作。

4

8 回答 8

53

大多数版本的 head(1) - 特别是 GNU 派生的,但不是 BSD 派生的 - 具有执行此操作的功能。如果您使用负数作为要打印的行数,它将显示文件的顶部,但末尾除外。

像这样:

head -n -10 textfile
于 2012-08-06T19:51:23.413 回答
15

可能比“wc”+“做数学”+“尾巴”方法效率低,但更容易看:

tail -r file.txt | tail +NUM | tail -r

哪里NUM比您要删除的结束行数多一,例如 +11 将打印除最后 10 行之外的所有行。这适用于不支持head -n -NUM语法的 BSD。

于 2012-10-24T19:18:01.097 回答
7

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
于 2012-08-06T19:51:57.190 回答
5

没有标准的命令可以做到这一点,但是您可以使用 awk 或 sed 来填充N行的缓冲区,并在它满后从头部打印。例如用 awk:

awk -v n=5 '{if(NR>n) print a[NR%n]; a[NR%n]=$0}' file
于 2012-08-06T21:19:07.763 回答
3
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
于 2018-10-07T05:52:31.207 回答
1

如果页脚以没有出现在其他地方的一致行开头,则可以使用sed

sed '/FIRST_LINE_OF_FOOTER/q' filename

打印页脚的第一行;如果你想避免这种情况:

sed -n '/FIRST_LINE_OF_FOOTER/q;p' filename

如果将来页脚的大小发生变化,这可能比计算行更可靠。(或者如果第一行发生变化,它可能会变得不那么健壮。)

head如果您的系统命令不支持,另一种选择head -n -10是预先计算要显示的行数。以下取决于特定于 bash 的语法:

lines=$(wc -l < filename) ; (( lines -= 10 )) ; head -$lines filename

请注意,为了向后兼容head -NUMBER,某些版本支持该语法;headPOSIX 只允许这种head -n NUMBER形式。POSIX 也只允许参数为-n十进制正整数;head -n 0不一定是无操作。

符合 POSIX 的解决方案是:

lines=$(wc -l < filename) ; lines=$(($lines - 10)) ; head -n $lines filename

如果你需要处理古老的 pre-POSIX shell,你可以考虑这个:

lines=`wc -l < filename` ; lines=`expr $lines - 10` ; head -n $lines filename

如果文件长度为 10 行或更少,这些中的任何一个都可能会做奇怪的事情。

于 2012-08-06T20:40:00.080 回答
0

tac 文件.txt | 尾 +[n+1] | tac

这个答案类似于 user9645 的,但它避免了 tail -r 命令,这在许多系统中也不是一个有效的选项。例如,参见https://ubuntuforums.org/showthread.php?t=1346596&s=4246c451162feff4e519ef2f5cb1a45f&p=8444785#post8444785作为示例。

请注意,在我尝试测试的系统上需要 +1(在括号中),但在您的系统上可能不需要它。因此,要删除最后一行,我必须将 2 放在括号中。这可能与您需要最后一行以常规换行符结尾的事实有关。可以说,这使最后一行成为空白行。如果您不这样做,则 tac 命令将合并最后两行,因此删除“最后”行(或 tail 命令的第一行)实际上将删除最后两行。

对于缺少改进版 head 的系统,我的回答也应该是迄今为止列出的最快的解决方案。所以,我认为它是列出的所有答案中最强大和最快的。

于 2019-02-13T16:34:23.323 回答
-1

很简单。您必须将 + 添加到要避免的行数。

此示例为您提供除前 9 行之外的所有行

tail -n +10 输入文件

(是的,不是前 10 个......因为它的计数不同......如果你想要 10 个,只需键入 tail -n 11 inputfile)

于 2013-10-01T22:30:28.807 回答