我有1000个文件,每个文件有一百万行。每一行都有以下形式:
a number,a text
我想从每个文件的每一行的开头删除所有数字。包括,
示例:
14671823,aboasdyflj -> aboasdyflj
我正在做的是:
os.system("sed -i -- 's/^.*,//g' data/*")
它工作正常,但需要花费大量时间。
最快的方法是什么?
我在python中编码。
答案 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)))
此外:
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!"