我想知道是否有人能帮我。
我正在编写一个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行,以便用自己的规则覆盖它。请问我做错了什么?
我想知道是否有人能帮我。
我正在编写一个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
根据您的具体情况,有多种方法可供选择。对于小型、格式良好的文件(例如小于1M,具有常规大小的行),您可以在ex
模式下使用Vim
:
ex -snc '$-11,$d|x' smallish_file.txt
-s
-> 静默模式;这是批处理,不需要UI(更快)-n
-> 这里不需要撤销缓冲区-c
-> 命令列表'$-11,$d'
-> 选择从末尾到倒数第11行的11行内容并删除。注意使用单引号以防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
-> 原地修改:将更改写入文件$
),以便Shell不会对其进行插值。但是对于较大的文件(比如超过几兆字节),使用上述方法效率不高。对于较大的文件,请使用中间/临时文件方法,就像其他答案所描述的那样。一个sed
方法:
tac some_file.txt | sed '1,12d' | tac > tmp && mv tmp some_file.txt
比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
中也做到吗?;-) - Mark Setchell就像这样:
head -n -12 test.txt > tmp.txt && cp tmp.txt test.txt
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
文件。
简单明了的脚本
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