I have two 3GB text files, each file has around 80 million lines. And they share 99.9% identical lines (file A has 60,000 unique lines, file B has 80,000 unique lines).
How can I quickly find those unique lines in two files? Is there any ready-to-use command line tools for this? I'm using Python but I guess it's less possible to find a efficient Pythonic method to load the files and compare.
Any suggestions are appreciated.
Если порядок имеет значение, попробуйте утилиту comm
. Если порядок не имеет значения, отсортировать файл1 файл2 | uniq -u
.
Если я правильно понял, вам нужны строки этих файлов без дубликатов. Это выполняет свою работу:
uniqA = set(open('fileA', 'r'))
Python имеет diffflib, который утверждает, что вполне конкурентоспособен с другими утилитами diff, см.: http://docs.python.org/library/difflib.html
Я думаю, что это самый быстрый метод (будь то Python или другой язык, IMO не имеет большого значения).
Примечания:
1. Я сохраняю хэш каждой строки только для экономии места (и времени, если может происходить разбиение на страницы)
2. Из-за вышеизложенного я распечатываю только номера строк; если вам нужны настоящие строки, вам просто нужно снова прочитать файлы
3. Я предполагаю, что хеш-функция не приводит к конфликтам. Это почти, но не совсем точно.
4. Я импортирую hashlib, потому что встроенная функция hash () слишком коротка, чтобы избежать конфликтов.
import sys
import hashlib
file = []
lines = []
for i in range(2):
# open the files named in the command line
file.append(open(sys.argv[1+i], 'r'))
# stores the hash value and the line number for each line in file i
lines.append({})
# assuming you like counting lines starting with 1
counter = 1
while 1:
# assuming default encoding is sufficient to handle the input file
line = file[i].readline().encode()
if not line: break
hashcode = hashlib.sha512(line).hexdigest()
lines[i][hashcode] = sys.argv[1+i]+': '+str(counter)
counter += 1
unique0 = lines[0].keys() - lines[1].keys()
unique1 = lines[1].keys() - lines[0].keys()
result = [lines[0][x] for x in unique0] + [lines[1][x] for x in unique1]
Имея 60 000 или 80 000 уникальных строк, вы можете просто создать словарь для каждой уникальной строки, сопоставив его с числом. mydict ["hello world"] => 1
и т. Д. Если ваша средняя строка составляет около 40-80 символов, это будет около 10 МБ памяти.
Затем прочтите каждый файл, преобразовав его в массив чисел через словарь. Они легко помещаются в память (2 файла по 8 байтов * 3 ГБ / 60 КБ строк меньше 1 МБ памяти). Затем сравните списки. Вы можете инвертировать словарь и использовать его для печати текста различающихся строк.
РЕДАКТИРОВАТЬ:
В ответ на ваш комментарий вот пример сценария, который присваивает номера уникальным строкам при чтении из файла.
#!/usr/bin/python
class Reader:
def __init__(self, file):
self.count = 0
self.dict = {}
self.file = file
def readline(self):
line = self.file.readline()
if not line:
return None
if self.dict.has_key(line):
return self.dict[line]
else:
self.count = self.count + 1
self.dict[line] = self.count
return self.count
if __name__ == '__main__':
print "Type Ctrl-D to quit."
import sys
r = Reader(sys.stdin)
result = 'ignore'
while result:
result = r.readline()
print result