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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4881930/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:09:30  来源:igfitidea点击:

Remove the last line from a file in Bash

bashcommand-linescriptingtruncate

提问by Fragsworth

I have a file, foo.txt, containing the following lines:

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

a
b
c

I want a simple command that results in the contents of foo.txtbeing:

我想要一个简单的命令,它的内容foo.txt是:

a
b

回答by thkala

Using GNU sed:

使用GNU sed

sed -i '$ d' foo.txt

The -ioption does not exist in GNU sedversions older than 3.95, so you have to use it as a filter with a temporary file:

-i选项在GNU sed3.95 之前的版本中不存在,因此您必须将其用作带有临时文件的过滤器:

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp

Of course, in that case you could also use head -n -1instead of sed.

当然,在这种情况下,您也可以使用head -n -1代替sed.

MacOS:

苹果系统:

On Mac OS X (as of 10.7.4), the equivalent of the sed -icommand above is

在 Mac OS X 上(从 10.7.4 开始),sed -i上面命令的等价物是

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

回答by John

This is by far the fastest and simplest solution, especially on big files:

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

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

if You want to delete the top line use this:

如果要删除顶行,请使用以下命令:

tail -n +2 foo.txt

which means output lines starting at line 2.

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

Do not use sedfor deleting lines from the top or bottom of a file -- it's very very slow if the file is large.

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

回答by Yossi Farjoun

I had trouble with all the answers here because I was working with a HUGE file (~300Gb) and none of the solutions scaled. Here's my solution:

我在这里的所有答案都遇到了麻烦,因为我正在处理一个巨大的文件(~300Gb)并且没有一个解决方案可以扩展。这是我的解决方案:

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

In words: Find out the length of the file you want to end up with (length of file minus length of length of its last line, using bc) and, set that position to be the end of the file (by dding one byte of /dev/nullonto it).

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

This is fast because tailstarts reading from the end, and ddwill overwrite the file in placerather than copy (and parse) every line of the file, which is what the other solutions do.

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

NOTE: This removes the line from the file in place! Make a backup or test on a dummy file before trying it out on your own file!

注意:这会从文件中删除该行!在您自己的文件上尝试之前,请先备份或测试一个虚拟文件!

回答by ohspite

To remove the last line from a file without reading the whole file or rewriting anything, you can use

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

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

To remove the last line and also print it on stdout ("pop" it), you can combine that command with tee:

要删除最后一行并将其打印在标准输出上(“弹出”它),您可以将该命令与tee

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

These commands can efficiently process a very large file. This is similar to, and inspired by, Yossi's answer, but it avoids using a few extra functions.

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

If you're going to use these repeatedly and want error handling and some other features, you can use the poptailcommand here: https://github.com/donm/evenmoreutils

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

回答by manpreet singh

Mac Users

Mac 用户

if you only want the last line deleted output without changing the file itself do

如果您只想删除最后一行的输出而不更改文件本身

sed -e '$ d' foo.txt

sed -e '$ d' foo.txt

if you want to delete the last line of the input file itself do

如果要删除输入文件本身的最后一行,请执行

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

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

回答by Sarfraaz Ahmed

For Mac Users :

对于 Mac 用户:

On Mac, head -n -1 wont work. And, I was trying to find a simple solution [ without worrying about processing time ] to solve this problem only using "head" and/or "tail" commands.

在 Mac 上, head -n -1 不起作用。而且,我试图找到一个简单的解决方案 [无需担心处理时间] 仅使用“head”和/或“tail”命令来解决这个问题。

I tried the following sequence of commands and was happy that I could solve it just using "tail" command [ with the options available on Mac ]. So, if you are on Mac, and want to use only "tail" to solve this problem, you can use this command :

我尝试了以下命令序列,很高兴我可以仅使用“tail”命令 [ 以及 Mac 上可用的选项 ] 来解决它。所以,如果你在 Mac 上,并且只想使用“tail”来解决这个问题,你可以使用这个命令:

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

猫文件.txt | 尾巴 -r | 尾 -n +2 | 尾-r

Explanation :

解释 :

1> tail -r : simply reverses the order of lines in its input

1> tail -r :简单地颠倒其输入中的行顺序

2> tail -n +2 : this prints all the lines starting from the second line in its input

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

回答by lhf

echo -e '$d\nw\nq'| ed foo.txt

回答by Foo Bah

awk 'NR>1{print buf}{buf = 
awk "NR != `wc -l < text.file`" text.file |> text.file
}'

Essentially, this code says the following:

本质上,这段代码说明如下:

For each line after the first, print the buffered line

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

for each line, reset the buffer

对于每一行,重置缓冲区

The buffer is lagged by one line, hence you end up printing lines 1 to n-1

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

回答by Michael Kingski

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)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}

This snippet does the trick.

这个片段可以解决问题。

回答by virtual-light

Both of these solutions are here in other forms. I found these a little more practical, clear, and useful:

这两种解决方案都以其他形式存在。我发现这些更实用、更清晰、更有用:

Using dd:

使用 dd:

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}

Using truncate:

使用截断:

##代码##