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

What is the fastest way to remove a number from the beginning of so many files?

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

a number,a text

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

示例:

14671823,aboasdyflj -> aboasdyflj

我正在做的是:

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

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

最快的方法是什么?

我正在 python 编码。

这要快得多:

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

对于一个包含 1100 万行的文件,它只用了不到一秒钟。

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

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

值得一提的是,与使用单独的文件相比,就地做事通常需要更长的时间。我尝试了您的 sed 命令,但从原地切换到临时文件。总时间从 26 秒减少到 9 秒。

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

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

例如,如果文件名有一个共同的前缀,如 file,您可以使用 shell globbing:

awk -F, -i inplace '{print }' file*

awk 将在应用就地修改时将每个文件视为不同的参数。


作为旁注,您可以直接 运行 shell 中的 shell 命令,而不是将其包装在 os.system() 中,这是不安全的,顺便说一句,在赞成 subprocess.

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

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!"

这可能非常快且原生 python。减少循环并使用 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)))

还有:

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