如何使用sed删除文件的最后n行

问题描述 投票:122回答:21

我想从文件末尾删除一些n行。这可以用sed完成吗?

例如,要删除2到4行,我可以使用

$ sed '2,4d' file

但我不知道行号。我可以删除最后一行使用

$sed $d file

但我想知道从最后删除n行的方法。请告诉我如何使用sed或其他方法来做到这一点。

linux bash shell sed
21个回答
190
投票

我不知道sed,但它可以用head完成:

head -n -2 myfile.txt

2
投票

通过这里的答案,您已经了解到sed不是此应用程序的最佳工具。

但是我确实认为使用sed有一种方法可以做到这一点;我的想法是附加N行来保持空间,直到你能够阅读而不会击中EOF。点击EOF时,打印保留空间的内容并退出。

sed -e '$!{N;N;N;N;N;N;H;}' -e x

上面的sed命令将省略最后5行。


2
投票

上面的大多数答案似乎都需要GNU命令/扩展:

    $ head -n -2 myfile.txt
    -2: Badly formed number

对于更轻松的解决方案:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

要么

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

要么

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

其中“10”是“n”。


2
投票

请尝试以下命令:

n = line number
tail -r file_name | sed '1,nd' | tail -r

1
投票

您可以使用wc -l <file>获取行的总数并使用

head -n <total lines - lines to remove> <file>


1
投票

它可以分3个步骤完成:

a)计算要编辑的文件中的行数:

 n=`cat myfile |wc -l`

b)从该数字中减去要删除的行数:

 x=$((n-3))

c)告诉sed从该行号($x)删除到最后:

 sed "$x,\$d" myfile

0
投票

我更喜欢这个解决方案

head -$(gcalctool -s $(cat file | wc -l)-N) file

其中N是要删除的行数。


0
投票
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

posix版本


0
投票

要删除最后4行:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

0
投票

我想出了这个,其中n是你想要删除的行数:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

这是一个小迂回,但我认为很容易遵循。

  1. 计算主文件中的行数
  2. 减去要从计数中删除的行数
  3. 打印出要保留的行数并存储在临时文件中
  4. 用temp文件替换主文件
  5. 删除临时文件

0
投票

这将删除file的最后3行:

for i in $(seq 1 3); do sed -i '$d' file; done;


27
投票

如果硬编码n是一个选项,您可以使用顺序调用sed。例如,要删除最后三行,删除最后一行三次:

sed '$d' file | sed '$d' | sed '$d'

0
投票

这将删除最后12行

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

0
投票

要删除文件的最后N行,可以使用相同的概念

$ sed '2,4d' file

您可以使用带有tail命令的组合来反转文件:如果N是5

$ tail -r file | sed '1,5d' file | tail -r > file

这种方式也运行head -n -5 file命令不运行(就像在Mac上!)。


24
投票

来自sed one-liners

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

似乎是你在寻找什么。


21
投票

一个有趣和简单的sedtac解决方案:

n=4
tac file.txt | sed "1,$n{d}" | tac

注意

  • shell需要双引号"来评估$n命令中的sed变量。在单引号中,不会执行插值。
  • taccat逆转,见man 1 tac
  • {}sed是分开$nd(如果没有,shell尝试插入不存在的$nd变量)

15
投票

使用sed,但让shell进行数学计算,目标是通过给出一个范围(删除最后23行)来使用d命令:

sed -i "$(($(wc -l < file)-22)),\$d" file

从内到外删除最后3行:

$(wc -l < file)

给出文件的行数:比如说2196

我们想删除最后23行,所以对于左侧或范围:

$((2196-22))

给出:2174因此,shell解释后的原始sed是:

sed -i '2174,$d' file

随着-i进行就地编辑,文件现在是2173行!

如果要将其保存到新文件中,代码为:

sed -i '2174,$d' file > outputfile

10
投票

你可以用头来做这个。

使用

$ head --lines=-N file > new_file

其中N是您要从文件中删除的行数。

原始文件的内容减去最后N行现在在new_file中


7
投票

为了完整起见,我想补充一下我的解决方案。我最终用标准的ed做到了这一点:

ed -s sometextfile <<< $'-2,$d\nwq'

这会使用就地编辑删除最后两行(尽管它确实使用了/tmp中的临时文件!!)


5
投票

要真正截断非常大的文件,我们有truncate命令。它不知道线,但tail + wc可以将行转换为字节:

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

如果文件同时写入,则存在明显的竞争条件。在这种情况下,最好使用head - 它从文件开头计算字节数(思维磁盘IO),因此我们将始终截断行边界(如果文件被主动写入,可能会比预期更多行):

truncate -s $(head -n -$lines $file | wc -c) $file

如果您失败登录尝试将密码替换为用户名,则方便一行:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

4
投票

这可能适合你(GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file
© www.soinside.com 2019 - 2024. All rights reserved.