有多种方法,具体取决于您的具体情况。对于格式良好的小型文件(例如,小于 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'
如果 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) -> 返回要删除的字节数
因此,您付钱并做出选择。明智地选择!