我有两个文件,全部.txt(525,953,272 条记录)和子集.txt(525,298,281 条记录)。每条记录只不过是一个 17 位 ASCII 整数。两个文件均已排序,并且每个文件中的重复记录已被删除。中的每个值子集.txt也存在于全部.txt。我希望找到以下记录全部.txt那些不在子集.txt。
我正在尝试diff
在这两个文件之间运行 a ,认为它会写出其中的行全部.txt但不在子集.txt。该机有64GB内存。已经diff
运行了半个小时,目前已经获取了75%左右的内存。
任何人都可以推测可能会发生什么,以及是否有论据diff
可能有帮助?这不是我diff
想要做的吗?我应该使用不同的方法吗?
答案1
任何人都可以推测可能会发生什么,以及 diff 是否有可能有帮助的论点?这不是 diff 的本意吗?我应该使用不同的方法吗?
这不是diff
本意要做的事;当输入已排序(如您所见)后,该作业的工具是comm
。
$ seq 10 15 > subset.txt
$ seq 10 20 > all.txt
$ comm -13 subset.txt all.txt
16
17
18
19
20
这选项comm
有点不寻常,因为它们会转动离开输出。第 1 列包含文件 1 特有的行;第 2 列包含文件 2 特有的行;第 3 列的行是两者“共有”的。通过使用选项,-13
我们要求 comm 向我们显示仅在“all.txt”中的行。
答案2
diff
可能不是最合适的工具。我会尝试编写一个简单的脚本来专门执行您想要的操作。
一切都在记忆中
这是一个非常简单且通用的解决方案。它将两个文件加载到最小的内存结构中,subset.txt
从 的记录中减去 的记录all.txt
并写出余数。
#!/usr/bin/env python
with open('diff.txt', 'w') as diff:
for record in set(open('all.txt', 'r')) - set(open('subset.txt', 'r')):
diff.write(record)
将其保存到类似 的文件中create_diff.py
,然后chmod +x create_diff.py
在两个文件所在的目录中运行它。
内存中唯一的子集
如果您需要进一步优化以降低内存占用量,也可以在不将整个文件加载到内存中的情况下实现这一点,特别是all.txt
不需要完全加载到内存中,而只需迭代一次。
#!/usr/bin/env python
subset_txt = open('subset.txt', 'r')
subset = subset_txt.readlines()
subset_txt.close()
with open('diff.txt', 'w') as diff_txt:
with open('all.txt', 'r') as all_txt:
for line in all_txt:
if line not in subset:
diff_txt.write(line)
基于输入/输出
这应该是最慢的变体,因为它严重依赖 I/O,但它的内存占用量较低,因为它不需要将整个文件加载到内存中。无论您的文件是否已排序/唯一,它都有效。
#!/usr/bin/env python
diff_txt = open('diff.txt', 'w')
with open('all.txt', 'r') as all_txt:
with open('subset.txt', 'r') as subset_txt:
for all_line in all_txt:
found = False
for sub_line in subset_txt:
if all_line == sub_line:
found = True
break
if found is False:
diff_txt.write(all_line)
subset_txt.seek(0)
diff_txt.close()
仅适用于无重复的排序文件<- 根据您的情况推荐
如果您确定两个文件都已排序并且不包含重复项,这应该是最好的解决方案。这两个文件都只读取一次,不需要完全加载到内存中。
#!/usr/bin/env python
diff_txt = open('diff.txt', 'w')
with open('all.txt', 'r') as all_txt:
with open('subset.txt', 'r') as subset_txt:
subset_line = subset_txt.readline()
for all_line in all_txt:
if all_line == subset_line:
subset_line = subset_txt.readline()
else:
diff_txt.write(all_line)
diff_txt.close()