如何删除文件的最后n行?

时间:2018-02-10 02:25:45

标签: linux bash

我想知道是否有人可以帮助我。

我正在编写一个bash脚本,我想删除特定文件的最后12行。

我环顾四周,不知何故拿出以下内容;

head -n -12 /var/lib/pgsql/9.6/data/pg_hba.conf | tee /var/lib/pgsql/9.6/data/pg_hba.conf >/dev/null

但是这会完全擦除文件。

我想做的就是永久删除该文件的最后12行,这样我就可以用自己的规则覆盖它。

任何关于我出错的帮助?

4 个答案:

答案 0 :(得分:4)

根据您的具体情况,有多种方法。对于小型,格式正确的文件(例如,小于1M,使用常规大小的行),您可以在Vim模式下使用ex

ex -snc '$-11,$d|x' smallish_file.txt
  • -s - >无声;这是批处理,因此没有必要的UI(更快)
  • -n - >这里不需要撤消缓冲区
  • -c - >命令列表
  • '$-11,$d' - >从末尾到末尾选择11行(总共12行)并删除它们。请注意单引号,以便shell不会将$d插入为变量。
  • x - > “写和退出”

对于类似的,可能更真实的回溯到'69,ed行编辑器可以为你做这个:

ed -s smallish_file.txt <<< $'-11,$d\nwq'
  • 请注意单引号之外的$,这与上面的ex命令不同。

如果Vim / ex和Ed很可怕,你可以使用sed获得一些shell帮助:

sed -i "$(($(wc -l < smallish_file.txt) - 11)),\$d" smallish_file.txt
  • -i - &gt; inplace :将更改写入文件
  • 总计12行的行数减去11。请注意转义的美元符号($),以便shell不插入它。

但是使用上述方法对于较大的文件(例如,超过几个meg)将不会有效。对于较大的文件,请使用中间/临时文件方法,如其他答案所述。 sed方法:

tac some_file.txt | sed '1,12d' | tac > tmp && mv tmp some_file.txt
  • tac以反转行顺序
  • sed删除最后一行(现在是第一行)12行
  • tac将撤回原始订单

效率高于sed的{​​{1}}方法:

head
  • head -n -12 larger_file.txt > tmp_file && mv tmp_file larger_file.txt 仅显示前NUM行。如我们所做的那样否定,显示最后最后NUM行。

但是为了实现真正的效率 - 可能对于真正大文件或者临时文件没有根据的地方 - 将文件截断到位。与其他涉及使用整个新内容覆盖整个旧文件的变体的方法不同,无论文件大小如何,这个方法都将近乎即时。

-n NUM

# In readable form: BYTES=$(tail -12 really_large.txt | wc -c) truncate -s -$BYTES really_large.txt # Inline, perhaps as part of a script truncate -s -$(tail -12 really_large.txt | wc -c) really_large.txt 命令使文件完全符合指定的大小(以字节为单位)。如果文件太短,它会使它变大,如果文件太大,它会真正切断多余的 。它使用文件系统语义来实现,因此它通常只需要写几个字节。这里的魔力在于计算切割的位置:

  • truncate - &gt;注意破折号/负面;说要将文件减少NUM个字节
  • -s -NUM - &gt;返回要删除的字节数

所以,你支付你的款项并做出你的选择。明智地选择!

答案 1 :(得分:0)

像这样:

head -n -12 test.txt > tmp.txt && cp tmp.txg test.txt

答案 2 :(得分:-1)

您可以使用临时文件存储-s

的中间结果

我认为以下代码应该有效:

head -n

如果你把它放在一个脚本上,那么代码就是更易读和易于维护:

 head -n -12 /var/lib/pgsql/9.6/data/pg_hba.conf  > /tmp/tmp.pg.hba.$$ && mv /tmp/tmp.pg.hba.$$ /var/lib/pgsql/9.6/data/pg_hba.conf

我建议在运行任何脚本之前备份 SRC_FILE=/var/lib/pgsql/9.6/data/pg_hba.conf TMP_FILE=/tmp/tmp.pg.hba.$$ head -n -12 $SRC_FILE > $TMP_FILE && mv $TMP_FILE $SRC_FILE

答案 3 :(得分:-1)

简单明了的脚本

declare -i start
declare -i cnt
cat dummy
1
2
3
4
5
6
7
8
9
10
11
12
13
cnt=`wc -l dummy|awk '{print $1}'`
start=($cnt-12+1)
sed "${start},\$d" dummy

OUTPUT 是第一行

1