是否有(POSIX 命令行)方法可以打印除最后 n 行之外的所有文件?用例是,我将有多个未知大小的文件,所有这些文件都包含一个已知大小的样板页脚,我想删除它。我想知道在自己编写之前是否已经有一个实用程序可以执行此操作。
8 回答
大多数版本的 head(1) - 特别是 GNU 派生的,但不是 BSD 派生的 - 具有执行此操作的功能。如果您使用负数作为要打印的行数,它将显示文件的顶部,但末尾除外。
像这样:
head -n -10 textfile
可能比“wc”+“做数学”+“尾巴”方法效率低,但更容易看:
tail -r file.txt | tail +NUM | tail -r
哪里NUM
比您要删除的结束行数多一,例如 +11 将打印除最后 10 行之外的所有行。这适用于不支持head -n -NUM
语法的 BSD。
该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
没有标准的命令可以做到这一点,但是您可以使用 awk 或 sed 来填充N行的缓冲区,并在它满后从头部打印。例如用 awk:
awk -v n=5 '{if(NR>n) print a[NR%n]; a[NR%n]=$0}' file
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
如果页脚以没有出现在其他地方的一致行开头,则可以使用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
,某些版本支持该语法;head
POSIX 只允许这种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 行或更少,这些中的任何一个都可能会做奇怪的事情。
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 的系统,我的回答也应该是迄今为止列出的最快的解决方案。所以,我认为它是列出的所有答案中最强大和最快的。
很简单。您必须将 + 添加到要避免的行数。
此示例为您提供除前 9 行之外的所有行
tail -n +10 输入文件
(是的,不是前 10 个......因为它的计数不同......如果你想要 10 个,只需键入 tail -n 11 inputfile)