从这么多文件的开头删除数字的最快方法是什么?

时间:2018-01-04 19:39:35

标签: regex bash performance shell text-processing

我有1000个文件,每个文件有一百万行。每一行都有以下形式:

a number,a text

我想从每个文件的每一行的开头删除所有数字。包括,

示例:

14671823,aboasdyflj -> aboasdyflj

我正在做的是:

os.system("sed -i -- 's/^.*,//g' data/*")

它工作正常,但需要花费大量时间。

最快的方法是什么?

我在python中编码。

4 个答案:

答案 0 :(得分:5)

这要快得多:

cut -f2 -d ',' data.txt > tmp.txt && mv tmp.txt data.txt

在一个包含1,100万行的文件上花了不到一秒钟。

要在目录中的多个文件上使用此功能,请使用:

TMP=/pathto/tmpfile
for file in dir/*; do
    cut -f2 -d ',' "$file" > $TMP && mv $TMP "$file"
done

值得一提的是,通常需要花费更长的时间才能使用单独的文件。我尝试了你的sed命令,但从原地切换到临时文件。总时间从26秒下降到9秒。

答案 1 :(得分:2)

我会使用GNU awk(利用-i inplace编辑文件)和,作为字段分隔符,没有昂贵的正则表达式操作

awk -F, -i inplace '{print $2}' file.txt

例如,如果文件名具有像file这样的公共前缀,则可以使用shell globbing:

awk -F, -i inplace '{print $2}' file*
在应用就地修改时,

awk会将每个文件视为不同的参数。

作为旁注,您可以直接在shell中运行shell命令,而不是将其包装在os.system()中,这是不安全的,不推荐使用BTW,而不是subprocess

答案 2 :(得分:2)

这可能很快&原生的蟒蛇。减少循环并使用csv.reader&在大多数实现中编译的csv.writer

import csv,os,glob
for f1 in glob.glob("*.txt"):
    f2 = f1+".new"
    with open(f1) as fr, open(f2,"w",newline="") as fw:
        csv.writer(fw).writerows(x[1] for x in csv.reader(fr))
    os.remove(f1)
    os.rename(f2,f1)  # move back the newfile into the old one

使用writerows&可能会更快map部分。 operator.itemgetter删除内循环:

csv.writer(fw).writerows(map(operator.itemgetter(1),csv.reader(fr)))

此外:

  • 它可以在所有系统上移植,包括没有安装MSYS的窗口
  • 在出现问题避免破坏输入的情况下,它会异常停止
  • 临时文件是故意在相同的文件系统中创建的,因此删除+重命名是超快的(而不是将临时文件移动到跨文件系统的输入,这需要shutil.move&将复制数据)

答案 3 :(得分:1)

您可以利用您的多核系统以及其他用户更快地处理特定文件的提示。

FILES = ['a', 'b', 'c', 'd']
CORES = 4

q = multiprocessing.Queue(len(FILES))

for f in FILES:
    q.put(f)

def handler(q, i):
    while True:
        try:
            f = q.get(block=False)
        except Queue.Empty:
            return
        os.system("cut -f2 -d ',' {f} > tmp{i} && mv tmp{i} {f}".format(**locals()))

processes = [multiprocessing.Process(target=handler, args=(q, i)) for i in range(CORES)]

[p.start() for p in processes]
[p.join() for p in processes]

print "Done!"