【问题标题】:How to delete the last n lines of a file? [duplicate]如何删除文件的最后n行? [复制]
【发布时间】:2018-07-20 20:40:36
【问题描述】:

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

我正在编写一个 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 行,以便我可以用我自己的规则覆盖它。

对我哪里出错有帮助吗?

【问题讨论】:

标签: linux bash


【解决方案1】:

像这样:

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

【讨论】:

    【解决方案2】:

    简单明了的脚本

    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
    

    输出 是第一行

    1
    

    【讨论】:

      【解决方案3】:

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

      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 -> 就地:将更改写入文件
      • 行数减去 11,总共 12 行。请注意转义的美元符号 ($),因此 shell 不会对其进行插值。

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

      tac some_file.txt | sed '1,12d' | tac > tmp && mv tmp some_file.txt
      
      • tac 反转行序
      • sed 删除最后(现在是第一个)12 行
      • tac 将返回原来的顺序

      sed 更有效的是head 方法:

      head -n -12 larger_file.txt > tmp_file && mv tmp_file larger_file.txt
      
      • -n NUM 仅显示前 NUM 行。正如我们所做的那样否定,显示直到最后 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 命令使文件精确到指定的字节大小。如果文件太短,它会变大,如果文件太大,它会非常有效地切掉多余的部分。它使用文件系统语义来做到这一点,因此它涉及的写入通常不超过几个字节。这里的魔力在于计算切碎的位置:

      • -s -NUM -> 注意破折号/负号;表示将文件减少 NUM 个字节
      • $(tail -12 really_large.txt | wc -c) -> 返回要删除的字节数

      因此,您付钱并做出选择。明智地选择!

      【讨论】:

      • 我发现了一个我自己时代的人!一些不错的见解!你也可以在edlin 做吗? ;-)
      【解决方案4】:

      您可以使用临时文件存储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
      

      我建议在运行任何脚本之前备份 /var/lib/pgsql/9.6/data/pg_hba.conf

      【讨论】:

      • 一行:F=/some/file; X=12; head -n -$X $F &gt; /tmp/tmpfile &amp;&amp; mv /tmp/tmpfile $F
      • 如果您使用的是 Mac:OS X 版本的 head 不允许负数,但您可以安装 core-utils 并使用 ghead
      猜你喜欢
      • 1970-01-01
      • 2018-05-14
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 2022-11-14
      相关资源
      最近更新 更多