Answers:
请尝试ed
:
ed <<< $'1d\nwq' large_file
如果“大”表示大约1000万行或更多,则更好地使用tail
。无法进行就地编辑,但是其性能使其无法原谅:
tail -n +2 large_file > large_file.new
编辑以显示一些时差:
(awk
Jaypal编写的代码被添加为在同一台计算机(CPU 2.2GHz)上具有执行时间。)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
awk
,得到了以下结果[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
的表现会接近sed
。(请注意:永远不要期望–可以代替测试。)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
我正在使用带锁的单个文件来跟踪多个进程使用的单个任务列表。我从最初的海报使用的开始sed -i 1d large_file
。这导致文件锁定1-2秒。该tail/mv
组合几乎立即完成。谢谢!
无法有效地从文件开头删除内容。从一开始就删除数据需要重写整个文件。
但是,从文件末尾截断可能会非常快(操作系统仅需调整文件大小信息,可能会清除当前未使用的块)。当您尝试从文件头删除时,通常这是不可能的。
如果您完全删除了整个块/范围,从理论上讲它可能是“快速”的,但是没有系统调用,因此您必须依靠特定于文件系统的语义(如果存在)。(我想,或者在第一个块/范围内有某种形式的偏移量来标记文件的真实开始。也从未听说过。)
最有效的方法,不要这样做!如果这样做,无论如何,您将需要磁盘上“大”空间的两倍,并且浪费IO。
如果卡住要读取的大文件而没有第一行,请等待直到需要读取它才能删除第一行。如果需要将文件从stdin发送到程序,请使用tail执行此操作:
tail -n +2 | your_program
当您需要读取文件时,可以趁机删除第一行,但前提是磁盘上有所需的空间:
tail -n +2 | tee large_file2 | your_program
如果您无法从stdin中读取内容,请使用fifo:
mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line
如果您正在使用bash,则更好,请利用进程替换:
your_program -i <(tail -n +2 large_file)
如果您需要在文件中进行搜索,那么我没有比不着手使用文件更好的解决方案。如果此文件是由stdout生成的:
large_file_generator | tail -n +2 > large_file
否则,总是有fifo或流程替换解决方案:
mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file
large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
tail
,我宁愿算时间做既除去第一行和替换bigfile.txt
用bigfile.new
。