从Bash中的文件中删除最后一行

Fra*_*rth 302 bash scripting command-line truncate

我有一个文件,foo.txt包含以下行:

a
b
c
Run Code Online (Sandbox Code Playgroud)

我想要一个简单的命令,导致内容为foo.txt:

a
b
Run Code Online (Sandbox Code Playgroud)

thk*_*ala 373

使用GNU sed:

sed -i '$ d' foo.txt
Run Code Online (Sandbox Code Playgroud)

-i选项在GNU sed早于3.95的版本中不存在,因此您必须将其用作具有临时文件的过滤器:

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp
Run Code Online (Sandbox Code Playgroud)

当然,在这种情况下你也可以使用head -n -1而不是sed.

苹果系统:

在Mac OS X上(从10.7.4开始),相当于sed -i上面的命令

sed -i '' -e '$ d' foo.txt
Run Code Online (Sandbox Code Playgroud)

  • 在Mac OS X上(截至10.7.4),上面的`sed -i`命令的等效命令是`sed -i''-e'$ d'foo.txt`.此外,`head -n -1`目前无法在Mac上运行. (54认同)
  • @Miro:绝不是'$ d`一个正则表达式.这是一个sed命令.`d`是删除行的命令,而`$`表示"文件中的最后一行".在命令之前指定位置(在sed术语中称为"范围")时,该命令仅应用于指定位置.所以,这个命令明确地说"在文件的最后一行的范围内,删除它".如果你问我的话,相当光滑,直截了当. (36认同)
  • 你能解释'$ d'正则表达式的作用吗?这是关于删除最后一行的问题,所以我认为这是每个人查看这个问题最重要的部分.谢谢 :) (25认同)
  • 你如何删除最后一行,但前提是它是一个空行? (2认同)

小智 267

这是迄今为止最快,最简单的解决方案,尤其是在大文件上:

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
Run Code Online (Sandbox Code Playgroud)

如果你想删除顶行使用这个:

tail -n +2 foo.txt
Run Code Online (Sandbox Code Playgroud)

这意味着输出线从第2行开始.

不要sed用于删除文件顶部或底部的行 - 如果文件很大,则非常慢.

  • @johannes_lalala在Mac上,您可以"brew install coreutils"(GNU核心实用程序)并使用`ghead`而不是`head`. (22认同)
  • head -n -1不适用于bdsutils的头部.至少不在macos版本中使用,所以这不起作用. (20认同)
  • `head -n -1 foo.txt`就足够了 (16认同)

Yos*_*oun 114

我在这里得到了所有答案的麻烦,因为我正在处理一个巨大的文件(~300Gb)并且没有任何解决方案缩放.这是我的解决方案:

dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
Run Code Online (Sandbox Code Playgroud)

在字:找出你想结束了(它的最后一行的长度的文件减去长度的长度,使用该文件的长度bc),并设置位置是文件的末尾(由dd荷兰国际集团的一个字节 /dev/null到它).

这是快,因为tail开始从终端读,dd将覆盖该文件的地方,而不是复制(和解析)文件的每一行,这是其他解决方案做.

注意:这将从文件中删除行!在您自己的文件上尝试之前,对虚拟文件进行备份或测试!

  • mac用户:dd if =/dev/null of = <filename> bs = 1 seek = $(echo $(stat -f =%z <filename> | cut -c 2-) - $(tail -n1 <filename> | wc -c)| bc) (8认同)
  • 非常非常聪明的方法!只需注意:它需要并在真实文件上运行,因此它不能用于管道,命令替换,重定向和此类链. (4认同)
  • 我甚至都不知道dd.这应该是最好的答案.非常感谢!很遗憾,该解决方案不适用于(阻止)gzip压缩文件. (3认同)
  • 这应该是最佳答案。立即为我的〜8 GB文件工作。 (3认同)
  • 您还可以直接使用 bash 计算要删除的字节数:`end_position=$(($file_size - $trim_count))` (3认同)
  • 这种方法是处理大文件的方法! (2认同)
  • 我拼命地浏览了前两个建议使用 `sed` 和 `head`+`&gt;` 的答案,是的,正是我所需要的,最后,非常感谢!**一定是最佳答案,完全同意!** (2认同)

ohs*_*ite 56

要从文件中删除最后一行而不读取整个文件或重写任何内容,您可以使用

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
Run Code Online (Sandbox Code Playgroud)

要删除最后一行并将其打印在stdout上("弹出"它),您可以将该命令与tee:

tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
Run Code Online (Sandbox Code Playgroud)

这些命令可以有效地处理非常大的文件.这与Yossi的回答类似,并受其启发,但它避免使用一些额外的功能.

如果您要反复使用这些并想要错误处理和其他一些功能,可以使用以下poptail命令:https: //github.com/donm/evenmoreutils

  • 快速注意:默认情况下,OS X上没有`truncate`.但是使用Brew很容易安装:`brew install tr​​uncate`. (3认同)
  • 非常好.没有dd会更好.我害怕使用dd作为一个错位的数字或字母可以拼写灾难.. + 1 (3认同)
  • (笑话警告)实际上, ("dd" --&gt; "disaster") 需要 1 次替换和 6 次插入;几乎不是“一个放错位置的数字或字母”。:) (2认同)
  • @malavv tail 从文件末尾向后读取以查找换行符...... (2认同)

man*_*ngh 29

Mac用户

如果你只想删除最后一行输出而不改变文件本身呢

sed -e '$ d' foo.txt

如果你想删除输入文件本身的最后一行呢

sed -i '' -e '$ d' foo.txt


Sar*_*med 24

对于Mac用户:

在Mac上,头-n -1不会工作.而且,我试图找到一个简单的解决方案[不用担心处理时间],只使用"head"和/或"tail"命令来解决这个问题.

我尝试了以下命令序列,并且很高兴我可以使用"tail"命令[使用Mac上的选项]来解决它.因此,如果您使用的是Mac,并且只想使用"tail"来解决此问题,则可以使用以下命令:

cat file.txt | tail -r | 尾巴-n +2 | 尾巴-r

说明:

1> tail -r:简单地反转输入中的行顺序

2> tail -n +2:这将打印从输入中的第二行开始的所有行

  • 使用Homebrew安装coreutils将使你的GNU头部为'ghead',允许你做`ghead -n -1` (2认同)

jas*_*ard 16

Linux

$表示最后一行,d表示删除:

sed '$d' ~/path/to/your/file/name
Run Code Online (Sandbox Code Playgroud)

苹果系统

相当于sed -i

sed -i '' -e '$ d' ~/path/to/your/file/name
Run Code Online (Sandbox Code Playgroud)


lhf*_*lhf 13

echo -e '$d\nw\nq'| ed foo.txt
Run Code Online (Sandbox Code Playgroud)

  • 对于不编辑文件的过滤器解决方案,请使用`sed'$ d'`. (2认同)

Foo*_*Bah 8

awk 'NR>1{print buf}{buf = $0}'
Run Code Online (Sandbox Code Playgroud)

基本上,此代码说明如下:

对于第一行之后的每一行,打印缓冲行

对于每一行,重置缓冲区

缓冲区滞后一行,因此最终会打印第1行到第n-1行

  • 此解决方案是一个过滤器,不会编辑该文件. (2认同)