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

mez*_*zda 132 linux bash shell sed

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

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

$ sed '2,4d' file
Run Code Online (Sandbox Code Playgroud)

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

$sed $d file
Run Code Online (Sandbox Code Playgroud)

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

ams*_*ams 198

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

head -n -2 myfile.txt
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这适用于某些版本的`head`,但不是标准版.实际上,`head`的标准是:`应用程序应确保number-argument-argument是一个正十进制整数 (60认同)
  • 添加到@WilliamPursell的答案...在Mac OS默认shell上,这不起作用. (20认同)
  • +1表示简单.等效的sed命令很难看:`sed -e:a -e'$ d; N; 2,5ba'-e'P; D'file`(`,5`代表最后5行). (17认同)
  • 也不是BSD,但问题是标记为Linux. (7认同)
  • 现在是 2019 年,我受到启发,以最矫枉过正的方式在 OSX 上使用 GNU head——通过使用 Docker:`docker run -v /Users/me/reports:/reports ubuntu head -n -7 /reports/ugly_footer。 csv` (5认同)
  • 答案很吸引人. (3认同)
  • 减去1,因为除了osx之外,这对我来说在Ubuntu14上不起作用 - "head:非法行数 - -2" (3认同)
  • 该行与 OSX 中的“ghead”一起使用。使用“brew install coreutils”安装 (3认同)

小智 27

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

sed '$d' file | sed '$d' | sed '$d'
Run Code Online (Sandbox Code Playgroud)

  • 加上-i来编辑文件而不是将其转储到stdout,对我有用. (2认同)

qst*_*bom 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
Run Code Online (Sandbox Code Playgroud)

似乎是你在寻找的东西.


Gil*_*not 22

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

n=4
tac file.txt | sed "1,$n{d}" | tac
Run Code Online (Sandbox Code Playgroud)

注意

  • "shell需要双引号来评估命令中的$n变量sed.在单引号中,不会执行插值.
  • tac是一个cat逆转,见man 1 tac
  • {}sed是否有分离$n&d(如果不是,壳尝试来内插不存在的$nd变量)

  • 在osx上没有`tac` (7认同)

lzc*_*lzc 18

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

sed -i "$(($(wc -l < file)-22)),\$d" file
Run Code Online (Sandbox Code Playgroud)

从内到外删除最后3行:

$(wc -l < file)
Run Code Online (Sandbox Code Playgroud)

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

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

$((2196-22))
Run Code Online (Sandbox Code Playgroud)

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

sed -i '2174,$d' file
Run Code Online (Sandbox Code Playgroud)

通过内部-i编辑,文件现在是2173行!


ric*_*ard 12

你可以用来做这个.

使用

$ head --lines=-N file > new_file

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

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


Mic*_*hel 7

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

ed -s sometextfile <<< $'-2,$d\nwq'
Run Code Online (Sandbox Code Playgroud)

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


pot*_*ong 5

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

sed ':a;$!N;1,4ba;P;$d;D' file
Run Code Online (Sandbox Code Playgroud)


小智 5

以上大部分答案似乎都需要 GNU 命令/扩展:

    $ head -n -2 myfile.txt
    -2: Badly formed number
Run Code Online (Sandbox Code Playgroud)

对于稍微更便携的解决方案:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'
Run Code Online (Sandbox Code Playgroud)

或者

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

或者

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

其中“10”是“n”。


Kam*_*ist 5

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

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file
Run Code Online (Sandbox Code Playgroud)

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

truncate -s $(head -n -$lines $file | wc -c) $file
Run Code Online (Sandbox Code Playgroud)

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

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure
Run Code Online (Sandbox Code Playgroud)