У меня есть два файла:
abc.txt
abcd
xyz
pqrs
mno.txt
zzon
mkno
abcd
Как я могу сделать это?
получить список:
grep -Fwf abc.txt mno.txt
это дает Вам что-то подобное:
abcd
abcd
zef
, если Вы хотите просто получить уникальный список затем, используют его как:
grep -Fwf abc.txt mno.txt | sort | uniq
и получить количества:
grep -Fcwv -f abc.txt mno.txt
<час> -F
средства: интерпретируйте ШАБЛОН как список фиксированных строк вместо регулярных выражений. -f
получают шаблоны из ФАЙЛА который, собираясь быть abc.txt
. mno.txt
для шаблонов -c
, рассчитывают, количество соответствий -w
Только ищут "целые слова": подстрока соответствия должна или быть в начале строки или предшествовала символом составляющей неслова. Точно так же это должно быть или в конце строки или сопровождается символом составляющей неслова. Составляющие Word символы являются буквами, цифрами и подчеркиванием. -v
Реверс поиск Если Ваша цель состоит в том, чтобы найти общие или редкие строки, comm
была бы моя дежурная команда здесь.
Это сравнивает два файла и шоу — в трех столбцах — строки, которые уникальны для файла 1, строки, которые уникальны для файла 2 и строк, которые появляются в обоих файлах, соответственно. Можно передать его флаги для подавления любого этого вывода также. Например, comm -1 file1 file2
подавит первый столбец, вещи, уникальные для file1. comm -12 file1 file2
только показал бы вещи в обоих файлах.
Существует один большой протест: вход должен быть отсортирован. Мы можем работать вокруг этого.
Это покажет Вам все в abc, которая не находится в mno:
comm -23 <(sort abc.txt) <(sort mno.txt)
И можно передать это по каналу в wc -l
получить количество.
Причина я иду с comm
это, после того как файлы отсортированы, бок о бок сравнение в вычислительном отношении действительно просто. Если Вы имеете дело с миллионами из них, которые будут иметь значение.
Это может быть продемонстрировано с несколькими ложными файлами. У меня есть довольно быстрый компьютер так для показа различия между подходами, мне нужен настоящий гигантский демонстрационный набор. Я перешел к 10 миллионам строк с 10 символами на файл.
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt
$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s
$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s
$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s
$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt | wc -l
... 0m12.161s
Сортировка - то, что берет большую часть времени в моем. Если мы притворяемся, что abc.txt статичен, мы можем предварительно отсортировать его, и это делает будущие сравнения намного быстрее:
$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s
Вы могли бы посмотреть на них и считать несколько секунд не важными, но я должен выделить это, они работают на высококачественной машине. Если Вы хотели сделать это на (например), Raspberry Pi 3, Вы будете смотреть на намного более медленные благоприятные повороты, и различие увеличится до точки, это на самом деле имеет значение.
Мы могли использовать awk, чтобы сделать задание путем передачи двух файлов, сначала файл шаблона, затем файл, который мы хотим проверить. Когда мы читаем первый файл, мы знаем это NR==FNR
и в то время мы можем считать строки в массив. Когда NR!=FNR
мы проверяем, установлен ли массив для такой строки.
$ cat abc.txt
abcd
xyz
pqrs
$ cat mno.txt
zzon
xyz
mkno
abcd
$ awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt
xyz
abcd
С другой стороны мы можем инвертировать шаблон для печати тех строк, которые не находятся в abc.txt
$ awk 'NR==FNR{a[$0]++};NR!=FNR && ! a[$0]' abc.txt mno.txt
zzon
mkno
И если мы хотим распечатать количество тех, мы можем использовать sort
и wc
:
$ awk 'NR==FNR{a[$0]++};NR!=FNR && ! a[$0]' abc.txt mno.txt | sort -u | wc -l
2
Если бы любой из списков слов не отсортирован, это было бы быстрее для использования эффективной структуры данных набора для запоминания общих слов.
#!/usr/bin/env python3
import sys
with open(sys.argv[1]) as minuend_file:
minuend = frozenset(map(str.rstrip, minuend_file))
with open(sys.argv[2]) as subtrahend_file:
subtrahend = frozenset(map(str.rstrip, subtrahend_file))
difference = minuend - subtrahend
#print(*difference, sep='\n') # This prints the content of the set difference
print(len(difference)) # This prints the magnitude of the set difference
Использование:
python3 set-difference.py abc.txt mno.txt
Если Вы хотите сохранить немного памяти для посреднического устройства хранения данных и время выполнения, можно использовать это немного более трудное понять программу:
#!/usr/bin/env python3
import sys
with open(sys.argv[1]) as minuend_file:
minuend = set(map(str.rstrip, minuend_file))
with open(sys.argv[2]) as subtrahend_file:
subtrahend = map(str.rstrip, subtrahend_file)
minuend.difference_update(subtrahend)
difference = minuend
del minuend
#print(*difference, sep='\n') # This prints the content of the set difference
print(len(difference)) # This prints the magnitude of the set difference
Данный abc.txt
и mno.txt
с 1 mio неотсортированные строки 10 случайных символов цифры ASCII каждый (см. ответ Oli для установки):
$ time python3 set-difference.py abc.txt mno.txt
user 0m10.453s
по сравнению с.
$ export LC_COLLATE=C
$ time sort abc.txt > abc_sorted.txt
user 0m10.652s
$ time sort mno.txt > mno_sorted.txt
user 0m10.767s
$ time comm -23 abc_sorted.txt mno_sorted.txt | wc -l
9989882
user 0m1.600s
общее количество: 23 секунды