这个问题已经在这里以一种或另一种形式提出,但不是我正在寻找的东西。所以,这就是我将遇到的情况:我已经有一个文件,命名file_a
并且我正在创建另一个文件 - file_b
. file_a 的大小始终大于 file_b。file_b 中会有许多重复的行(因此,在 file_a 中也是如此),但两个文件都有一些独特的行。我想要做的是:仅复制/合并唯一行 from file_a
tofile_b
然后对行顺序进行排序,以便 file_b 成为具有所有唯一条目的最新行。任何一个原始文件的大小都不应超过 10MB。我能做到这一点的最有效(和最快)的方法是什么?
我在想这样的事情,合并没问题。
#!/usr/bin/env python
import os, time, sys
# Convert Date/time to epoch
def toEpoch(dt):
dt_ptrn = '%d/%m/%y %H:%M:%S'
return int(time.mktime(time.strptime(dt, dt_ptrn)))
# input files
o_file = "file_a"
c_file = "file_b"
n_file = [o_file,c_file]
m_file = "merged.file"
for x in range(len(n_file)):
P = open(n_file[x],"r")
output = P.readlines()
P.close()
# Sort the output, order by 2nd last field
#sp_lines = [ line.split('\t') for line in output ]
#sp_lines.sort( lambda a, b: cmp(toEpoch(a[-2]),toEpoch(b[-2])) )
F = open(m_file,'w')
#for line in sp_lines:
for line in output:
if "group_" in line:
F.write(line)
F.close()
但是,它是:
- 不仅有独特的线条
- 未排序(按最后一个字段)
- 并介绍了第三个文件,即
m_file
只是一个旁注(长话短说):不幸的是,我不能在这里使用 sorted(),因为我使用的是 v2.3。输入文件如下所示:
On 23/03/11 00:40:03
JobID Group.User Ctime Wtime Status QDate CDate
===================================================================================
430792 group_atlas.pltatl16 0 32 4 02/03/11 21:52:38 02/03/11 22:02:15
430793 group_atlas.atlas084 30 472 4 02/03/11 21:57:43 02/03/11 22:09:35
430794 group_atlas.atlas084 12 181 4 02/03/11 22:02:37 02/03/11 22:05:42
430796 group_atlas.atlas084 8 185 4 02/03/11 22:02:38 02/03/11 22:05:46
我尝试使用 cmp() 按倒数第二个字段进行排序,但我认为它不起作用只是因为输入文件的前 3 行。
有人可以帮忙吗?干杯!!!
更新1:
为了将来参考,正如 Jakob 所建议的,这里是完整的脚本。它工作得很好。
#!/usr/bin/env python
import os, time, sys
from sets import Set as set
def toEpoch(dt):
dt_ptrn = '%d/%m/%y %H:%M:%S'
return int(time.mktime(time.strptime(dt, dt_ptrn)))
def yield_lines(fileobj):
#I want to discard the headers
for i in xrange(3):
fileobj.readline()
#
for line in fileobj:
yield line
def app(path1, path2):
file1 = set(yield_lines(open(path1)))
file2 = set(yield_lines(open(path2)))
return file1.union(file2)
# Input files
o_file = "testScript/03"
c_file = "03.bak"
m_file = "finished.file"
print time.strftime('%H:%M:%S', time.localtime())
# Sorting the output, order by 2nd last field
sp_lines = [ line.split('\t') for line in app(o_file, c_file) ]
sp_lines.sort( lambda a, b: cmp(toEpoch(a[-2]),toEpoch(b[-2])) )
F = open(m_file,'w')
print "No. of lines: ",len(sp_lines)
for line in sp_lines:
MF = '\t'.join(line)
F.write(MF)
F.close()
完成 145244 行大约需要 2m:47s。
[testac1@serv07 ~]$ ./uniq-merge.py
17:19:21
No. of lines: 145244
17:22:08
谢谢!!
更新 2:
嗨 eyquem,这是我在运行脚本时收到的错误消息。
从第一个脚本:
[testac1@serv07 ~]$ ./uniq-merge_2.py
File "./uniq-merge_2.py", line 44
fm.writelines( '\n'.join(v)+'\n' for k,v in output )
^
SyntaxError: invalid syntax
从第二个脚本:
[testac1@serv07 ~]$ ./uniq-merge_3.py
File "./uniq-merge_3.py", line 24
output = sett(line.rstrip() for line in fa)
^
SyntaxError: invalid syntax
干杯!!
更新 3:
前一个根本没有对列表进行排序。感谢 eyquem 指出这一点。嗯,现在可以了。这是对 Jakob 版本的进一步修改 - 我将 set:app(path1, path2) 转换为 list:myList() ,然后将 sort( lambda ... ) 应用于myList
通过嵌套对合并文件进行排序到最后场地。这是最终的脚本。
#!/usr/bin/env python
import os, time, sys
from sets import Set as set
def toEpoch(dt):
# Convert date/time to epoch
dt_ptrn = '%d/%m/%y %H:%M:%S'
return int(time.mktime(time.strptime(dt, dt_ptrn)))
def yield_lines(fileobj):
# Discard the headers (1st 3 lines)
for i in xrange(3):
fileobj.readline()
for line in fileobj:
yield line
def app(path1, path2):
# Remove duplicate lines
file1 = set(yield_lines(open(path1)))
file2 = set(yield_lines(open(path2)))
return file1.union(file2)
print time.strftime('%H:%M:%S', time.localtime())
# I/O files
o_file = "testScript/03"
c_file = "03.bak"
m_file = "finished.file"
# Convert set into to list
myList = list(app(o_file, c_file))
# Sort the list by the date
sp_lines = [ line.split('\t') for line in myList ]
sp_lines.sort( lambda a, b: cmp(toEpoch(a[-2]),toEpoch(b[-2])) )
F = open(m_file,'w')
print "No. of lines: ",len(sp_lines)
# Finally write to the outFile
for line in sp_lines:
MF = '\t'.join(line)
F.write(MF)
F.close()
根本没有速度提升,处理相同的 145244 行需要 2m:50s。有没有人看到任何改进的范围,请告诉我。感谢 Jakob 和 eyquem 的时间。干杯!!
更新 4:
仅供将来参考,这是eyguem的修改版本,它比以前的版本更好更快。
#!/usr/bin/env python
import os, sys, re
from sets import Set as sett
from time import mktime, strptime, strftime
def sorting_merge(o_file, c_file, m_file ):
# RegEx for Date/time filed
pat = re.compile('[0123]\d/[01]\d/\d{2} [012]\d:[0-6]\d:[0-6]\d')
def kl(lines,pat = pat):
# match only the next to last field
line = lines.split('\t')
line = line[-2]
return mktime(strptime((pat.search(line).group()),'%d/%m/%y %H:%M:%S'))
output = sett()
head = []
# Separate the header & remove the duplicates
def rmHead(f_n):
f_n.readline()
for line1 in f_n:
if pat.search(line1): break
else: head.append(line1) # line of the header
for line in f_n:
output.add(line.rstrip())
output.add(line1.rstrip())
f_n.close()
fa = open(o_file, 'r')
rmHead(fa)
fb = open(c_file, 'r')
rmHead(fb)
# Sorting date-wise
output = [ (kl(line),line.rstrip()) for line in output if line.rstrip() ]
output.sort()
fm = open(m_file,'w')
# Write to the file & add the header
fm.write(strftime('On %d/%m/%y %H:%M:%S\n')+(''.join(head[0]+head[1])))
for t,line in output:
fm.write(line + '\n')
fm.close()
c_f = "03_a"
o_f = "03_b"
sorting_merge(o_f, c_f, 'outfile.txt')
这个版本要快得多 - 6.99 秒。对于 145244 行,与 2m:47s 相比 - 然后前一个使用lambda a, b: cmp()
. 感谢 eyquem 的所有支持。干杯!!