在Python中使用grep搜索文件
我在这里查找关于grep的答案,但找不到合适的。大家似乎都在讨论如何在文件中搜索一个字符串,而不是从文件中读取字符串列表。我已经有一个可以用的搜索功能,但grep的速度快得多。我在一个名为sn.txt的文件里有一串字符串(每行一个字符串,没有分隔符)。我想在另一个文件(Merge_EXP.exp)中查找包含这些字符串的行,并把结果写入一个新文件。要知道,我要搜索的文件有五十万行,所以在里面找几千个字符串没有grep的话要花好几个小时。
当我在Windows的命令提示符下运行这个命令时,几分钟就能完成:
grep --file=sn.txt Merge_EXP.exp > Merge_EXP_Out.exp
我想知道如何从Python中调用这个相同的过程?我不太想要Python中的其他替代方案,因为我已经有一个可以用但速度慢的。如果你觉得能显著提高我的那个方法的性能,那也可以。
def match_SN(serialnumb, Exp_Merge, output_exp):
fout = open(output_exp,'a')
f = open(Exp_Merge,'r')
# skip first line
f.readline()
for record in f:
record = record.strip().rstrip('\n')
if serialnumb in record:
fout.write (record + '\n')
f.close()
fout.close()
def main(Output_CSV, Exp_Merge, updated_exp):
# create a blank output
fout = open(updated_exp,'w')
# copy header records
f = open(Exp_Merge,'r')
header1 = f.readline()
fout.write(header1)
header2 = f.readline()
fout.write(header2)
fout.close()
f.close()
f_csv = open(Output_CSV,'r')
f_csv.readline()
for rec in f_csv:
rec_list = rec.split(",")
sn = rec_list[2]
sn = sn.strip().rstrip('\n')
match_SN(sn,Exp_Merge,updated_exp)
3 个回答
我觉得你给问题起的标题不太合适:你想做的事情其实相当于数据库中的JOIN操作。你可以在这种情况下使用grep,因为你其中一个文件只有键,没有其他信息。不过,我觉得将来你的sn.txt文件可能也会包含额外的信息。
所以我建议你解决一个更通用的情况。这里有几种解决方案:
- 把所有数据导入数据库,然后进行左连接(LEFT JOIN)或者类似的操作
- 使用Python的大数据工具
对于后者,你可以尝试numpy,或者因为你在处理字符串,推荐使用pandas。根据我的经验,Pandas有一个优化的合并功能,速度非常快(底层使用了cython)。
以下是用pandas解决你问题的伪代码。虽然这接近真实代码,但我需要知道你想匹配的列名。我假设在sn.txt
中有一列叫key
,而在merge_txt
中匹配的列叫sn
。我还注意到你在merge_exp中有两行标题,建议你查阅相关文档了解更多。
# PSEUDO CODE (but close)
import pandas
left = pandas.read_csv('sn.txt')
right = pandas.read_csv('merge_exp.exp')
out = pandas.merge(left, right, left_on="key", right_on="sn", how='left')
out.to_csv("outx.txt")
这是一个优化过的纯Python代码版本:
def main(Output_CSV, Exp_Merge, updated_exp):
output_list = []
# copy header records
records = open(Exp_Merge,'r').readlines()
output_list = records[0:2]
serials = open(Output_CSV,'r').readlines()
serials = [x.split(",")[2].strip().rstrip('\n') for x in serials]
for s in serials:
items = [x for x in records if s in x]
output_list.extend(items)
open(updated_exp, "w").write("".join(output_list))
main("sn.txt", "merge_exp.exp", "outx.txt")
输入
sn.txt文件:
x,y,0011
x,y,0002
merge_exp.exp文件:
Header1
Header2
0011abc
0011bcd
5000n
5600m
6530j
0034k
2000lg
0002gg
输出
Header1
Header2
0011abc
0011bcd
0002gg
试试看这个,看看它需要多长时间...
当我使用grep的完整路径时,它可以正常工作(我给它传递了grep_loc、Serial_List和Export这些参数):
import os
Export_Dir = os.path.dirname(Export)
Export_Name = os.path.basename(Export)
Output = Export_Dir + "\Output_" + Export_Name
print "\nOutput: " + Output + "\n"
cmd = grep_loc + " --file=" + Serial_List + " " + Export + " > " + Output
print "grep usage: \n" + cmd + "\n"
os.system(cmd)
print "Output created\n"