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

a
b
c

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

a
b

当前回答

这是目前为止最快和最简单的解决方案,特别是对大文件:

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt

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

tail -n +2 foo.txt

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

不要使用sed从文件的顶部或底部删除行——如果文件很大,它会非常非常慢。

其他回答

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

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}

要删除最后一行并将其打印到stdout(“弹出”它),可以将该命令与tee结合使用:

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

这些命令可以有效地处理一个非常大的文件。这与Yossi的答案相似,并受到了启发,但它避免了使用一些额外的函数。

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

Linux

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

sed '$d' ~/path/to/your/file/name

操作系统

相当于sed -i:

sed -i '' -e '$ d' ~/path/to/your/file/name

对于大文件

我在这里遇到了所有答案的麻烦,因为我正在使用一个巨大的文件(~300Gb),没有一个解决方案缩放。以下是我的解决方案:

filename="example.txt"

file_size="$(stat --format=%s "$filename")"
trim_count="$(tail -n1 "$filename" | wc -c)"
end_position="$(echo "$file_size - $trim_count" | bc)"

dd if=/dev/null of="$filename" bs=1 seek="$end_position"

或者,作为一行:

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

简言之:找出您想要结束的文件的长度(文件的长度减去其最后一行的长度,使用bc),并将该位置设置为文件的结束位置(通过在其上添加/dev/null的一个字节)。

这是快速的,因为tail从末尾开始读取,dd将就地覆盖文件,而不是复制(并解析)文件的每一行,这是其他解决方案所做的。

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

OK处理了大量的数据,输出是OK的,但有一个垃圾行。

如果我用管道输出脚本到:

| sed -i '$ d'我将得到以下错误,最终没有输出 Sed:没有输入文件

但是|头-n -1成功了!

awk "NR != `wc -l < text.file`" text.file &> newtext.file

这段代码可以达到目的。