Найти идентификаторы в одном файле, которые не находятся в другом

У меня есть два файла:

abc.txt

abcd xyz pqrs

abc.txt

zzon mkno abcd Я хочу чтобы проверить, есть ли «abcd» в файле mno.txt. Не обязательно, что если «abcd» является первым в abc.txt, он также будет первым в mno.txt. В обоих файлах есть тысячи таких идентификаторов. Я хочу также проверить, сколько идентификаторов нет в mno.txt, которые находятся в abc.txt.

Как я могу это сделать?

9
задан 26 June 2017 в 15:55

8 ответов

Если какой-либо из списков слов несортирован, было бы быстрее использовать эффективную структуру данных для запоминания общих слов.

Python

#!/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

Python (более эффективно)

Если вы хотите сохранить небольшую память для промежуточного хранения и времени выполнения, вы можете использовать эту несколько более сложную для понимания программу:

#!/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-цифр каждый (см. ответ Оли для настройки):

$ time python3 set-difference.py abc.txt mno.txt user 0m10.453s

vs.

$ 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 секунды

2
ответ дан 18 July 2018 в 11:06

Если ваша цель - найти общие или необычные строки, comm будет моей командой go-to здесь.

Он сравнивает два файла и показывает - в трех столбцах - строки, которые уникальны для файла 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, вы будете смотреть на гораздо более медленные обороты, и разница будет увеличиваться до такой степени, что это имеет значение.

19
ответ дан 18 July 2018 в 11:06

Мы могли бы использовать 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
3
ответ дан 18 July 2018 в 11:06

, чтобы получить список:

grep -Fwf abc.txt mno.txt

он дает вам нечто похожее на:

abcd abcd zef

, если вы хотите просто получить уникальный список, используйте его как: [ ! d2] grep -Fwf abc.txt mno.txt | sort | uniq

и для получения отсчетов:

grep -Fcwv -f abc.txt mno.txt -F означает: интерпретировать PATTERN как список фиксированных строк вместо регулярных выражений. -f получить шаблоны из ФАЙЛА, который будет abc.txt. мы рассмотрим mno.txt для паттернов -c Подсчитайте количество совпадений -w. Ищите только «целые слова»: соответствующая подстрока должна либо находиться в начале строки, либо должна предшествовать несимметричному составляющему символу. Точно так же он должен быть либо в конце строки, либо сопровождаться неглавным составным символом. Символы Word - это буквы, цифры и символ подчеркивания. -v Отменить поиск
7
ответ дан 18 July 2018 в 11:06

Если какой-либо из списков слов несортирован, было бы быстрее использовать эффективную структуру данных для запоминания общих слов.

Python

#!/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

Python (более эффективно)

Если вы хотите сохранить небольшую память для промежуточного хранения и времени выполнения, вы можете использовать эту несколько более сложную для понимания программу:

#!/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-цифр каждый (см. ответ Оли для настройки):

$ time python3 set-difference.py abc.txt mno.txt user 0m10.453s

vs.

$ 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 секунды

2
ответ дан 24 July 2018 в 19:43

Если ваша цель - найти общие или необычные строки, comm будет моей командой go-to здесь.

Он сравнивает два файла и показывает - в трех столбцах - строки, которые уникальны для файла 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, вы будете смотреть на гораздо более медленные обороты, и разница будет увеличиваться до такой степени, что это имеет значение.

19
ответ дан 24 July 2018 в 19:43

Мы могли бы использовать 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
3
ответ дан 24 July 2018 в 19:43
  • 1
    Я думаю, что вы ошибаетесь. Насколько я понимаю, OP хочет вычислить (размер) заданную разницу abc.txt - mno.txt, которая есть {xyz, pqrs}. – David Foerster 27 June 2017 в 16:27

, чтобы получить список:

grep -Fwf abc.txt mno.txt

он дает вам нечто похожее на:

abcd abcd zef

, если вы хотите просто получить уникальный список, используйте его как: [ ! d2] grep -Fwf abc.txt mno.txt | sort | uniq

и для получения отсчетов:

grep -Fcwv -f abc.txt mno.txt -F означает: интерпретировать PATTERN как список фиксированных строк вместо регулярных выражений. -f получить шаблоны из ФАЙЛА, который будет abc.txt. мы рассмотрим mno.txt для паттернов -c Подсчитайте количество совпадений -w. Ищите только «целые слова»: соответствующая подстрока должна либо находиться в начале строки, либо должна предшествовать несимметричному составляющему символу. Точно так же он должен быть либо в конце строки, либо сопровождаться неглавным составным символом. Символы Word - это буквы, цифры и символ подчеркивания. -v Отменить поиск
7
ответ дан 24 July 2018 в 19:43
  • 1
    Если OP хочет получить count из не , не должно ли это быть больше похоже на grep -cxvFf abc.txt mno.txt? – steeldriver 26 June 2017 в 15:50
  • 2
    Просто увидел это: D ... ты всегда здесь, чтобы спасти меня: D – Ravexina 26 June 2017 в 15:50
  • 3
    FYI альтернативы fgrep, egrep предположительно устарели (в пользу grep -F, grep -E - хотя я не уверен, что кто-то считает, что они когда-нибудь уйдут – steeldriver 26 June 2017 в 15:52
  • 4
    Нужно ли использовать -x при использовании -F? – Ravexina 26 June 2017 в 15:54
  • 5
    Это зависит от того, что OP хочет точно подсчитать - например, если mno.txt содержит abcdef, следует считать совпадение или несоответствие с abcd? – steeldriver 26 June 2017 в 16:01

Другие вопросы по тегам:

Похожие вопросы: