我有一个文件, foo.txt ,包含以下行:
foo.txt
a b c
我想要一个简单的命令,导致 foo.txt 的内容为:
a b
使用GNU sed:
sed -i '$ d' foo.txt
-i 选项在早于3.95的 GNU sed 版本中不存在,因此您必须将其用作带有临时文件的过滤器:
-i
GNU sed
cp foo.txt foo.txt.tmp sed '$ d' foo.txt.tmp > foo.txt rm -f foo.txt.tmp
当然,在这种情况下,您也可以使用 head -n -1 而不是 sed .
head -n -1
sed
MacOS:
在Mac OS X上(从10.7.4开始),相当于上面的 sed -i 命令
sed -i
sed -i '' -e '$ d' foo.txt
这是迄今为止最快,最简单的解决方案,尤其是在大文件上:
head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt
如果你想删除顶行使用这个:
tail -n +2 foo.txt
这意味着输出线从第2行开始 .
不要使用 sed 删除文件顶部或底部的行 - 如果文件很大,则速度非常慢 .
我在这里得到了所有答案的麻烦,因为我正在使用一个巨大的文件(~300Gb)并且没有任何解决方案缩放 . 这是我的解决方案:
dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )
单词:找出你想要最终得到的文件的长度(文件长度减去最后一行长度的长度,使用 bc ),并将该位置设置为文件的结尾(通过 dd 一个字节) /dev/null 到它上面) .
bc
dd
/dev/null
这很快,因为 tail 从头开始读取, dd 将覆盖文件 in place 而不是复制(和解析)文件的每一行,这是其他解决方案所做的 .
tail
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!
要从文件 without reading the whole file or rewriting anything 中删除最后一行,您可以使用
tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}
要删除最后一行并将其打印在stdout("pop"它)上,您可以将该命令与 tee 组合:
tee
tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})
这些命令可以有效地处理非常大的文件 . 这与Yossi的回答类似,并受其启发,但它避免使用一些额外的功能 .
如果您要反复使用这些并想要错误处理和其他一些功能,可以在此处使用 poptail 命令:https://github.com/donm/evenmoreutils
poptail
Mac用户
如果你只想删除最后一行输出而不改变文件本身呢
sed -e '$ d' foo.txt
如果你想删除输入文件本身的最后一行呢
在Mac上,头-n -1不会工作 . 而且,我试图找到一个简单的解决方案[不用担心处理时间],只使用“head”和/或“tail”命令来解决这个问题 .
我尝试了以下命令序列,并且很高兴我可以使用“tail”命令[使用Mac上的选项]来解决它 . 因此,如果您使用的是Mac,并且只想使用“tail”来解决此问题,则可以使用以下命令:
cat file.txt | tail -r |尾巴-n 2 |尾巴-r
1> tail -r:简单地反转输入中的行顺序
2> tail -n 2:打印输入中从第二行开始的所有行
echo -e '$d\nw\nq'| ed foo.txt
awk 'NR>1{print buf}{buf = $0}'
基本上,此代码说明如下:
对于第一行之后的每一行,打印缓冲行
对于每一行,重置缓冲区
缓冲区滞后一行,因此最终会打印第1行到第n-1行
awk "NR != `wc -l < text.file`" text.file |> text.file
这个片段可以解决这个问题 .
这两种解决方案都以其他形式出现 . 我发现这些更实用,清晰,有用:
使用dd:
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}
使用截断:
BADLINESCOUNT=1 ORIGINALFILE=/tmp/whatever truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}
红宝石(1.9)
ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file
11 回答
使用GNU sed:
-i
选项在早于3.95的GNU sed
版本中不存在,因此您必须将其用作带有临时文件的过滤器:当然,在这种情况下,您也可以使用
head -n -1
而不是sed
.MacOS:
在Mac OS X上(从10.7.4开始),相当于上面的
sed -i
命令这是迄今为止最快,最简单的解决方案,尤其是在大文件上:
如果你想删除顶行使用这个:
这意味着输出线从第2行开始 .
不要使用
sed
删除文件顶部或底部的行 - 如果文件很大,则速度非常慢 .我在这里得到了所有答案的麻烦,因为我正在使用一个巨大的文件(~300Gb)并且没有任何解决方案缩放 . 这是我的解决方案:
单词:找出你想要最终得到的文件的长度(文件长度减去最后一行长度的长度,使用
bc
),并将该位置设置为文件的结尾(通过dd
一个字节)/dev/null
到它上面) .这很快,因为
tail
从头开始读取,dd
将覆盖文件 in place 而不是复制(和解析)文件的每一行,这是其他解决方案所做的 .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!
要从文件 without reading the whole file or rewriting anything 中删除最后一行,您可以使用
要删除最后一行并将其打印在stdout("pop"它)上,您可以将该命令与
tee
组合:这些命令可以有效地处理非常大的文件 . 这与Yossi的回答类似,并受其启发,但它避免使用一些额外的功能 .
如果您要反复使用这些并想要错误处理和其他一些功能,可以在此处使用
poptail
命令:https://github.com/donm/evenmoreutils如果你只想删除最后一行输出而不改变文件本身呢
sed -e '$ d' foo.txt
如果你想删除输入文件本身的最后一行呢
sed -i '' -e '$ d' foo.txt
对于Mac用户:
在Mac上,头-n -1不会工作 . 而且,我试图找到一个简单的解决方案[不用担心处理时间],只使用“head”和/或“tail”命令来解决这个问题 .
我尝试了以下命令序列,并且很高兴我可以使用“tail”命令[使用Mac上的选项]来解决它 . 因此,如果您使用的是Mac,并且只想使用“tail”来解决此问题,则可以使用以下命令:
说明:
1> tail -r:简单地反转输入中的行顺序
2> tail -n 2:打印输入中从第二行开始的所有行
基本上,此代码说明如下:
对于第一行之后的每一行,打印缓冲行
对于每一行,重置缓冲区
缓冲区滞后一行,因此最终会打印第1行到第n-1行
这个片段可以解决这个问题 .
这两种解决方案都以其他形式出现 . 我发现这些更实用,清晰,有用:
使用dd:
使用截断:
红宝石(1.9)