快速从多个文本文件中删除前n行

3

我需要通过删除输入文件的前两行来创建一个输出文本文件。

目前,我正在使用 sed "1,2d" input.txt > output.txt

我需要对成千上万个文件执行此操作,因此使用python:

import os
for filename in somelist:
  os.system('sed "1,2d" %s-in.txt > %s-out.txt'%(filename,filename))

但是这个方法非常慢。

我需要保留原始文件,所以我不能在原地进行sed。

有没有更快的方法?除了sed之外还可以使用其他工具吗?也许可以使用一些比Python更适合的脚本语言?编写一个简短的C程序值得吗,或者文件写入和磁盘访问可能成为瓶颈?


使用os.system()的一个问题是每个循环都会生成一个新的shell,这会增加一些开销。直接在例如bash中的循环中运行将稍微减少开销(但性能提高可能只是理论上的,因为磁盘I/O是限制因素,正如其他人所提到的)。 - pafcu
如果文件都只有四行,那么它可能不是那么理论性的问题。但我想使用exec而不是system也可以得到几乎相同的改进。这并不需要一个shell。 - Cascabel
3个回答

10

使用 tail 命令。我怀疑没有什么能够比它更快:

tail -n +3 input.txt > output.txt

用你选择的循环将其包装起来。但我真的怀疑sed会慢很多——因为正如你所说,磁盘I/O通常是最终的瓶颈。


谢谢,我刚刚尝试了一下,它在运行时间上与原始版本基本无法区分(就像ghostdog的sed -i.bak一样),所以我怀疑这是一个I/O瓶颈。 - Samizdis
我知道我不可能得到答案,但是为什么这个被踩了呢?这是在nix中执行此操作的规范方法。 - Cascabel

4
我认为这比启动sed更快:
import os
import shutil

path = '/some/path/to/files/'
for filename in os.listdir(path):
    basename, ext = os.path.splitext(filename)
    fullname = os.path.join(path, filename)
    newname = os.path.join(path, basename + '-out' + ext)
    with open(fullname) as read:
        #skip first two lines
        for n in xrange(2):
            read.readline()
        # hand the rest to shutil.copyfileobj
        with open(newname, 'w') as write:
            shutil.copyfileobj(read, write)

3
for file in *.ext
do
    sed -i.bak -n '3,$p' $file 
done

或者只是
sed -i.bak -n '3,$p' *.ext

非常感谢,但不幸的是,似乎I/O是瓶颈。 - Samizdis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接