Найти строки из файла, которых нет в другом файле
У меня есть два файла (скажем a.txt
и b.txt
), оба из которых имеют список имен. Я уже запускал sort
для обоих файлов.
Теперь я хочу найти строки из a.txt
, которые отсутствуют в b.txt
.
(Я потратил много времени, чтобы найти ответ на этот вопрос, поэтому документирую его для будущей справки)
Ответы
Ответ 1
Команда, которую вы должны использовать, не diff
, а comm
comm -23 a.txt b.txt
По умолчанию comm
выводит 3 столбца: только слева, только справа. Переключатели -1
, -2
и -3
подавляют эти столбцы.
Итак, -23
скрывает правый и оба столбца, показывая строки, которые появляются только в первом (левом) файле.
Если вы хотите найти строки, которые появляются в обоих, вы можете использовать -12
, который скрывает только левый и правый столбцы, оставляя вас только с обоими столбцами.
Ответ 2
Простой ответ не сработал у меня, потому что я не понимал, что comm
соответствует строке для строки, поэтому дубликаты строк в одном файле будут напечатаны как не существующие в другом. Например, если файл1 содержит:
Alex
Bill
Fred
И файл2 содержит:
Alex
Bill
Bill
Bill
Fred
Затем comm -13 file1 file2
выводит:
Bill
Bill
В моем случае я хотел знать только, что каждая строка в файле2 существовала в файле1, независимо от того, сколько раз эта строка встречалась в каждом файле.
Решение 1: используйте флаг -u
(unique) для sort
:
comm -13 <(sort -u file1) <(sort -u file2)
Решение 2: (первый "рабочий" ответ, который я нашел) из unix.stackexchange:
fgrep -v -f file1 file2
Обратите внимание, что если file2 содержит повторяющиеся строки, которые вообще не существуют в файле1, fgrep
выводит каждую из повторяющихся строк. Также обратите внимание, что мои совершенно ненаучные тесты на одном ноутбуке для одного (довольно большого) набора данных показали, что решение 1 (с использованием comm
) будет почти в 5 раз быстрее, чем решение 2 (используя fgrep
).
Ответ 3
В случае, если файлы еще не отсортированы, вы можете использовать:
comm -23 <(sort a.txt) <(sort b.txt)
Ответ 4
Я не уверен, почему было сказано, что diff
не должно использоваться. Я бы использовал его для сравнения двух файлов, а затем выводил только строки, которые находятся в левом файле, но не в правильном. Такие строки помечены diff с помощью <
, поэтому достаточно grep этот символ в начале строки
diff a.txt b.txt | grep \^\<