Найти строки из файла, которые отсутствуют в другом файле [дубликат]

этот вопрос уже есть ответ здесь:

у меня есть два файла (скажем a.txt и b.txt), оба из которых имеют список имен. Я уже бежал sort на обоих файлах.

теперь я хочу найти строки из a.txt которых нет в b.txt.

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

4 ответов


команда, которую вы должны использовать, не diff но comm

comm -23 a.txt b.txt

по умолчанию comm выводит 3 столбца:осталось только, право-только, и. The -1, -2 и -3 переключатели подавляют эти столбцы.

и -23 скрыть право-только и и столбцы, показывающие строки, которые отображаются только в первом (левом) файле.

если вы хотите найти строки которые появляются в обоих, вы можете использовать -12, который скрывает осталось только и право-только столбцы, оставляя вас только с и.


простой ответ не сработал для меня, потому что я не понял comm соответствует строке для строки, поэтому повторяющиеся строки в одном файле будут напечатаны как не существующие в другом. Например, если file1 содержит:

Alex
Bill
Fred

и file2 содержит:

Alex
Bill
Bill
Bill
Fred

затем comm -13 file1 file2 выводит:

Bill
Bill

в моем случае я хотел знать только, что каждая строка в file2 существует в file1, независимо от того, сколько раз эта строка произошла в каждом файл.

Решение 1: использовать -u (уникальный) флаг sort:

comm -13 <(sort -u file1) <(sort -u file2)

решение 2: (первый "рабочий" ответ, который я нашел) из unix.клиент StackExchange:

fgrep -v -f file1 file2

обратите внимание, что если file2 содержит повторяющиеся строки, которые вообще не существуют в file1,fgrep выведет каждую из повторяющихся строк. Также обратите внимание, что мои совершенно ненаучные тесты на одном ноутбуке для одного (довольно большого) набора данных показано Решение 1 (используя comm) почти в 5 раз быстрее, чем решение 2 (используя fgrep).


Я не уверен, почему это было сказано diff Не следует использовать. Я бы использовал его для сравнения двух файлов, а затем выводил только строки, которые находятся в левом файле, но не в правом. Такие линии помечены diff с < поэтому достаточно grep этот символ в начале строки

diff a.txt b.txt  | grep \^\<

в случае, если файлы еще не будут отсортированы, вы можете использовать:

comm -23 <(sort a.txt) <(sort b.txt)