188

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

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

$ sed '2,4d' file

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

$sed $d file

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

4

23 回答 23

261

我不知道sed,但可以通过以下方式完成head

head -n -2 myfile.txt
于 2012-11-14T14:26:41.250 回答
38

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

sed '$d' file | sed '$d' | sed '$d'
于 2014-06-19T03:16:25.070 回答
34

sed 单线

# 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

似乎是你正在寻找的东西。

于 2012-11-14T16:49:32.927 回答
26

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

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

笔记

  • shell需要双引号"来评估命令中的$n变量sed。在单引号中,不会执行插值。
  • taccat反转的,见man 1 tac
  • {}insed是用来分隔$n&的d(如果不是,shell 会尝试插入不存在的$nd变量)
于 2012-11-14T15:34:53.443 回答
25

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

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
于 2016-12-16T15:27:12.123 回答
20

您可以为此使用head 。

利用

$ head --lines=-N file > new_file

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

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

于 2012-11-14T14:29:29.457 回答
13

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

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

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

于 2015-10-23T08:24:31.737 回答
6

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

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

如果同时写入文件,则存在明显的竞争条件。在这种情况下,使用它可能会更好head——它从文件的开头计算字节数(mind disk IO),所以我们总是会在行边界上截断(如果文件被主动写入,可能会比预期的行多):

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

如果您尝试使用密码代替用户名登录失败,则方便单行:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure
于 2016-02-19T19:50:37.620 回答
5

上述大多数答案似乎都需要 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”。

于 2014-08-12T03:51:01.753 回答
5

这可能对您有用(GNU sed):

sed ':a;$!N;1,4ba;P;$d;D' file
于 2012-11-14T16:26:43.310 回答
2

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

但是我确实认为使用 sed 可以做到这一点;这个想法是附加 N 行以保持空间,直到您能够阅读而不会碰到 EOF。当 EOF 被命中时,打印保持空间的内容并退出。

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

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

于 2012-11-14T15:13:46.053 回答
2

它可以通过 3 个步骤完成:

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

 n=`cat myfile |wc -l`

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

 x=$((n-3))

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

 sed "$x,\$d" myfile
于 2016-10-03T18:10:15.443 回答
1

尝试以下命令:

n = line number
tail -r file_name | sed '1,nd' | tail -r
于 2015-03-16T10:34:21.207 回答
1

您可以获得总行数wc -l <file>和使用

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

于 2014-04-24T12:46:04.170 回答
1

这将从中删除最后 3 行file

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

于 2016-01-12T18:39:32.603 回答
0

要删除最后 4 行:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   
于 2015-01-21T17:41:44.813 回答
0
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

正版

于 2015-01-22T09:25:38.987 回答
0

我更喜欢这个解决方案;

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

其中N是要删除的行数。

于 2014-07-23T13:08:46.550 回答
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. 用临时文件替换主文件
  5. 删除临时文件
于 2015-05-21T18:48:54.167 回答
0

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

$ sed '2,4d' file

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

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

而且这种方式也可以在head -n -5 file命令不运行的地方运行(就像在 mac 上一样!)。

于 2019-04-24T15:36:11.597 回答
0

在 docker 中,这对我有用:

head --lines=-N file_path >> file_path
于 2020-08-21T23:04:31.697 回答
0
#!/bin/sh

echo 'Enter the file name : '
read filename

echo 'Enter the number of lines from the end that needs to be deleted :'
read n

#Subtracting from the line number to get the nth line
m=`expr $n - 1`

# Calculate length of the file
len=`cat $filename|wc -l`

#Calculate the lines that must remain
lennew=`expr $len - $m`

sed "$lennew,$ d" $filename
于 2021-06-05T18:46:08.213 回答
-2

这将删除最后 12 行

sed -n -e :a -e '1,10!{P;N;D;};N;ba'
于 2018-05-24T19:39:41.447 回答