我试图获取文件的最后一行然后将其删除:
阅读该行:
sed -n '$p' file
# or
tail -n 1 file
删除该行:
sed -i '$d' file
这可行,但是有没有办法做到这一点单个命令?
答案1
无论普遍的观点是什么,每次都必须读取整个文件才能截断其最后一行哑的,无论它是在单个进程/命令中还是在两个或三个进程/命令中完成。
与 不同的是sed -i
,tail
它足够聪明,不会从头读取文件以确定其最后一行是什么;另外,linux 有一个truncate(1)
实用程序,它tail
可以让您在 O(1) 时间内“弹出”一个大文件的最后一行:
# usage popline file [line_count, 1 by default]
popline()(LC_CTYPE=C; l=`tail -n "${2:-1}" "$1"; echo t`; l=${l%t}; truncate -s "-${#l}" "$1"; printf %s "$l")
$ wc -l /tmp/foo
3579500 /tmp/foo
$ cp /tmp/foo /tmp/foo1 && time sed -i '$d' /tmp/foo1
real 0m1.077s
user 0m0.457s
sys 0m0.156s
$ cp /tmp/foo /tmp/foo1 && time popline /tmp/foo1
*/
real 0m0.052s
user 0m0.002s
sys 0m0.003s
答案2
目标是使用一个命令输出文件的最后一行,同时从原始文件中删除该行。
sed -i -e '${w /dev/stdout' -e 'd;}' file
这将运行以下sed
脚本:
${
w /dev/stdout
d
}
这将写入最后一行/dev/stdout
,然后将其删除。所有其他行都通过该选项写回原始文件-i
。
命令行上的脚本必须分成两部分,因为无法以其他方式分隔命令的输出文件名w
(除了插入文字换行符之外)。
和ed
:
ed -s file <<END_ED
p
d
w
END_ED
ed
打开文件file
并将光标置于文件的最后一行。第一个命令将该行打印到标准输出,第二个命令删除它,最后一个命令将缓冲区写回文件。对于大文件,可能不建议使用ed
这种方式。