2011-01-23 2 views
1

У меня есть список слов (180k и 260k), и я хотел бы сгенерировать третий файл, который представляет собой набор слов, которые появляются в списках BOTH.Пересечение двух больших списков слов

Каков наилучший (самый эффективный) способ сделать это? Я читал форумы, говоря об использовании grep, однако я думаю, что списки слов слишком велики для этого метода.

ответ

4

Если эти два файла отсортированы (или вы можете отсортировать их), вы можете использовать comm -1 -2 file1 file2 для распечатки перекрестка.

+0

Оказывается, один из них сортируется - могли бы вы дать мне команду, чтобы отсортировать другую? – pjama

+0

Просто 'sort -o outfile infile', если другой файл также отсортирован в алфавитном порядке. Однако будьте осторожны с локалями; в частности, может ли порядок быть «AaBb» или «ABab» может измениться. Чтобы быть в безопасности, вы можете явно сортировать оба файла, чтобы убедиться, что используете одни и те же настройки. –

+0

Спасибо за помощь. Иеремия! Сорт работал нормально, но * comm * все еще предупреждал «comm: file 2 не в отсортированном порядке» - но он, похоже, сгенерировал * something *. Звучит это нормально? Я буду делать QA утром :) – pjama

3

Вы правы, grep будет плохой идеей. Введите «человек присоединится к» и следуйте инструкциям.

Если ваши файлы только списки слов в одном столбце, или, по крайней мере, если важное слово является первым в каждой строке, то все, что вам нужно сделать, это:

$ sort -b -o f1 file1 
$ sort -b -o f2 file2 
$ join f1 f2 

В противном случае, вы может понадобиться, чтобы дать присоединиться (1) команда некоторые дополнительные инструкции:

JOIN(1)     BSD General Commands Manual     JOIN(1) 

NAME 
    join -- relational database operator 

SYNOPSIS 
    join [-a file_number | -v file_number] [-e string] [-o list] [-t char] [-1 field] [-2 field] file1 file2 

DESCRIPTION 
    The join utility performs an ``equality join'' on the specified files and writes the result to the standard output. The ``join field'' is the field in each file by which the files are compared. The 
    first field in each line is used by default. There is one line in the output for each pair of lines in file1 and file2 which have identical join fields. Each output line consists of the join field, 
    the remaining fields from file1 and then the remaining fields from file2. 
    . . . 
    . . . 
2

, предполагающих одно слово в каждой строке, я хотел бы использовать grep:

grep -xFf seta setb 
  • -x соответствует целые строки (не частичные совпадения)
  • -F интерпретирует данные модели буквально (не регулярных выражений)
  • -f seta задает шаблоны для поиска
  • setb является файл для поиска содержимого из seta

comm будет делать то же самое, но требует ваши наборы для предварительной сортировки:

comm -12 <(sort seta) <(sort setb) 
+1

* grep -xFf * также работал и, похоже, дает тот же результат (судя по равному количеству строк в результате). Я думаю, что это заняло немного больше времени (вычислительно), чем метод * comm * (как и следовало ожидать, конечно). Благодаря! – pjama

1

grep -P '[ A-Za-z0-9]*' file1 | xargs -0 -I {} grep {} file2 > file3

Я считаю, что это выглядит для чего в file1, затем проверяет, является ли то, что было в ФАЙЛ1 в file2, и выставляет все, что соответствует в file3.

0

В те дни мне удалось найти скрипт на Perl, который делает что-то подобное:

http://www.perlmonks.org/?node_id=160735

+0

Обратите внимание, что [ссылки только ответов] (http://meta.stackoverflow.com/tags/link-only-answers/info) не приветствуются, SO ответы должны быть конечной точкой поиска решения (vs. еще одна остановка ссылок, которые со временем становятся устаревшими). Пожалуйста, подумайте о добавлении отдельного резюме здесь, сохранив ссылку в качестве ссылки. – kleopatra

Смежные вопросы