pLu*_*umo 6 sed text-processing
我正在尝试获取文件的最后一行,然后将其删除:
阅读该行:
sed -n '$p' file
# or
tail -n 1 file
Run Code Online (Sandbox Code Playgroud)
删除该行:
sed -i '$d' file
Run Code Online (Sandbox Code Playgroud)
这是有效的,但是有没有办法只用一个命令来做到这一点?
mos*_*svy 11
无论流行的智慧是什么,为了切断最后一行而每次都必须读取整个文件是愚蠢的,无论它是在单个进程/命令中完成还是在两个或三个中完成。
不像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
Run Code Online (Sandbox Code Playgroud)
目标是让一个命令输出文件的最后一行,同时从原始文件中删除该行。
sed -i -e '${w /dev/stdout' -e 'd;}' file
Run Code Online (Sandbox Code Playgroud)
这将运行以下sed脚本:
${
w /dev/stdout
d
}
Run Code Online (Sandbox Code Playgroud)
这将写入最后一行/dev/stdout,然后将其删除。所有其他行都通过-i选项写回原始文件。
命令行上的脚本必须一分为二,因为无法以其他方式分隔w命令的输出文件名(除了插入文字换行符)。
与ed:
ed -s file <<END_ED
p
d
w
END_ED
Run Code Online (Sandbox Code Playgroud)
ed打开文件file并将光标放在文件的最后一行。第一个命令将该行打印到标准输出,第二个命令删除它,最后一个命令将缓冲区写回文件。ed以这种方式使用可能不适用于大文件。