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

时间:2011-02-03 01:45:21

标签: bash command-line scripting truncate

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

a
b
c

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

a
b

16 个答案:

答案 0 :(得分:343)

使用GNU sed

sed -i '$ d' foo.txt

早于3.95的-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

<强>的MacOS:

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

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

答案 1 :(得分:248)

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

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

如果你想删除顶行,请使用:

tail -n +2 foo.txt

表示从第2行开始的输出行。

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

答案 2 :(得分:103)

我在这里得到了所有答案的麻烦,因为我正在处理一个巨大的文件(~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的一个字节到它上面。

这很快,因为tail从最后开始阅读,dd将覆盖文件到位,而不是复制(和解析)文件的每一行,这是其他解决方案所做的。

注意:这会从文件中删除该行!在虚拟文件上进行备份或测试,然后在自己的文件上进行尝试!

答案 3 :(得分:51)

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

Sub DeleteCells()

    Dim R As Range
    'Set rng = Nothing
    On Error Resume Next
    Set R = Application.InputBox("Select cells To be deleted", Type:=8)
    Dim rng As Range
   Dim rngError As Range
  Set rng = Sheets("Sheet3").Range("A1:G100")
   Set rngError = rng.Cells.SpecialCells(xlCellTypeFormulas, xlErrors)

   If TypeName(R) <> "Range" Then
        Exit Sub
    Else
    R.delete
   End If



For Each cell In rng
 If cell.Text = "#REF!" Then
  cell.EntireColumn.delete
 End If
     'delete means cells will move up after deleting that entire row
     'rngError.EntireRow.ClearContents means that the contents will clear, leaving a blank cell for that entire row
Next




End Sub

要删除最后一行并在stdout上打印(&#34; pop&#34;它),您可以将该命令与tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{} 结合使用:

tee

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

如果您要反复使用这些并想要错误处理和其他一些功能,可以在此处使用tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{}) 命令: https://github.com/donm/evenmoreutils

答案 4 :(得分:28)

  

Mac用户

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

sed -e '$ d' foo.txt

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

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

答案 5 :(得分:23)

对于Mac用户:

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

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

  

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

说明:

1&GT; tail -r:简单地反转其输入中的行的顺序

2 - ; tail -n +2:这将打印从输入

中的第二行开始的所有行

答案 6 :(得分:12)

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

答案 7 :(得分:8)

awk 'NR>1{print buf}{buf = $0}'

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

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

每行

,重置缓冲区

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

答案 8 :(得分:0)

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

这个片段可以解决问题。

答案 9 :(得分:0)

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

使用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}

使用truncate:

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

答案 10 :(得分:0)

这是您手动执行的操作(当我需要快速删除文件的最后一行时,我个人经常使用此方法):

vim + [FILE]

那里的+符号表示在vim文本编辑器中打开文件时,光标将位于文件的最后一行。

现在只需在键盘上按两次d。这将完全满足您的要求-删除最后一行。之后,先按:,再按x,然后按Enter。这将保存更改,并带您回到Shell。因此,最后一行已被成功删除。

答案 11 :(得分:0)

Linux

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

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

MacOS

相当于sed -i

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

答案 12 :(得分:0)

您也可以尝试使用此方法:删除最后n行的示例。

a = 0; while [$ a -lt 4]; sed -i'$ d'output.txt; a = expr $a + 1;完成

从文件(output.txt)中删除最后4行。

答案 13 :(得分:0)

以下是使用海绵的解决方案(来自moreutils包):

head -n -1 foo.txt | sponge foo.txt

解决方案摘要:

  1. 如果您想为大型文件提供快速解决方案,请使用efficient taildd方法。

  2. 如果您想要一些易于扩展/调整和可移植的内容,请使用redirect and move方法。

  3. 如果您希望轻松扩展/调整某些内容,则文件不会太大,可移植性(即取决于moreutils包)不是问题,并且是方形裤子的粉丝,请考虑使用海绵方法。

与“重定向和移动”方法相比,海绵方法的一个好处是海绵可以保留文件权限。

与“重定向和移动”方法相比,海绵使用了更多的RAM。这样可以提高速度(仅约20%),但是如果您对速度感兴趣,则可以采用“有效尾巴”和dd方式。

答案 14 :(得分:0)

可以处理大量数据,输出也可以,但有一个垃圾行。

如果我将脚本的输出通过管道传输到:

| sed -i '$ d' 我会得到以下错误,最后根本没有输出 sed:没有输入文件

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

答案 15 :(得分:-4)

红宝石(1.9 +)

ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file