Remove the last line from a file in Bash
我有一个文件
1 2 3 | a b c |
我想要一个简单的命令,导致
1 2 | a b |
使用
1 | sed -i '$ d' foo.txt |
1 2 3 | cp foo.txt foo.txt.tmp sed '$ d' foo.txt.tmp > foo.txt rm -f foo.txt.tmp |
当然,在这种情况下,您也可以使用
苹果系统:
在Mac OS X(从10.7.4版本开始)上,与上述
1 | sed -i '' -e '$ d' foo.txt |
这是迄今为止最快,最简单的解决方案,尤其是在大文件上:
1 | head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt |
如果要删除第一行,请使用以下命令:
1 | tail -n +2 foo.txt |
这意味着输出线从第2行开始。
不要使用
我在这里遇到的所有问题都遇到了麻烦,因为我正在使用巨大的文件(?300Gb),并且没有解决方案可以扩展。这是我的解决方案:
1 | dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc ) |
换句话说:找出要结束的文件的长度(文件长度减去最后一行的长度,使用
这是快速的,因为
注意:这将从适当的文件中删除该行!在尝试对自己的文件进行备份之前,请对虚拟文件进行备份或测试!
要从文件中删除最后一行而不读取整个文件或重写任何内容,可以使用
1 | tail -n 1"$file" | wc -c | xargs -I {} truncate"$file" -s -{} |
要删除最后一行并在stdout上打印("弹出"它),可以将该命令与
1 | tail -n 1"$file" | tee >(wc -c | xargs -I {} truncate"$file" -s -{}) |
这些命令可以有效地处理非常大的文件。这与Yossi的答案相似并受其启发,但是避免了使用一些额外的功能。
如果要重复使用这些命令,并且需要错误处理和其他一些功能,则可以在此处使用
https://github.com/donm/evenmoreutils
Mac Users
如果只希望最后一行删除输出而不更改文件本身,
如果要删除输入文件本身的最后一行,请执行
对于Mac用户:
在Mac上,head -n -1不起作用。并且,我试图找到一种简单的解决方案[无需担心处理时间]仅使用" head"和/或" tail"命令来解决此问题。
我尝试了以下命令序列,并很高兴我可以仅使用" tail"命令(使用Mac上的可用选项)来解决它。因此,如果您使用的是Mac,并且只想使用" tail"来解决此问题,则可以使用以下命令:
cat file.txt | tail -r | tail -n +2 | tail -r
说明:
1> tail -r:简单地反转其输入中的行顺序
2> tail -n +2:这将打印输入中从第二行开始的所有行
1 2 3 | echo -e '$d w q'| ed foo.txt |
1 | awk 'NR>1{print buf}{buf = $0}' |
本质上,此代码说明以下内容:
对于第一行之后的每一行,打印缓冲的行
对于每一行,重置缓冲区
缓冲区被一行滞后,因此最终打印行1到n-1
的Linux
$是最后一行,d表示删除:
1 | sed '$d' ~/path/to/your/file/name |
苹果系统
相当于sed -i
1 | sed -i '' -e '$ d' ~/path/to/your/file/name |
这是您可以手动执行的操作(当我需要快速删除文件的最后一行时,我个人经常使用此方法):
1 | vim + [FILE] |
那里的
现在,只需在键盘上按两次
这两种解决方案都以其他形式出现。我发现这些更加实用,清晰和有用:
使用dd:
1 2 3 4 5 | BADLINESCOUNT=1 ORIGINALFILE=/tmp/whatever dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf"$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c) " | bc ) /bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE} |
使用截断:
1 2 3 4 | BADLINESCOUNT=1 ORIGINALFILE=/tmp/whatever truncate -s $(printf"$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c) " | bc ) ${ORIGINALFILE} |
1 | awk"NR != `wc -l < text.file`" text.file |> text.file |
此代码片段可以解决问题。
红宝石(1.9+)
1 | ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file |