Сравните два файла по строкам и создайте разницу в другом файле

Я хочу сравнить файл1 с файлом 2 и сгенерировать файл3, который содержит строки в файле1, которых нет в файле2.

Ответ 1

diff (1) не является ответом, но comm (1) есть.

NAME
       comm - compare two sorted files line by line

SYNOPSIS
       comm [OPTION]... FILE1 FILE2

...

       -1     suppress lines unique to FILE1

       -2     suppress lines unique to FILE2

       -3     suppress lines that appear in both files

Итак,

comm -2 -3 file1 file2 > file3

Входные файлы должны быть отсортированы. Если это не так, сначала сортируйте их. Это можно сделать с помощью временного файла или...

comm -2 -3 <(sort file1) <(sort file2) > file3

при условии, что ваша оболочка поддерживает замещение процесса (bash делает).

Ответ 2

Утилита Unix diff предназначена именно для этой цели.

$ diff -u file1 file2 > file3

См. руководство и Интернет для параметров, разных форматов вывода и т.д.

Ответ 3

Рассмотрим это:
file a.txt:

abcd
efgh

файл b.txt:

abcd

Вы можете найти разницу:

diff -a --suppress-common-lines -y a.txt b.txt

Выход будет:

efgh 

Вы можете переназначить вывод в выходном файле (c.txt), используя:

diff -a --suppress-common-lines -y a.txt b.txt > c.txt

Это ответит на ваш вопрос:

"... который содержит строки в файле1, которые не присутствует в файле2."

Ответ 4

Иногда diff - это полезная утилита, но иногда подходит join. Файлы должны быть предварительно отсортированы или, если вы используете оболочку, которая поддерживает замещение процесса, например bash, ksh или zsh, вы можете выполнить сортировку на лету.

join -v 1 <(sort file1) <(sort file2)

Ответ 5

Попробуйте

sdiff file1 file2

В большинстве случаев он работает намного лучше для меня. Вы можете захотеть отсортировать файлы ранее, если порядок строк не важен (например, некоторые текстовые файлы конфигурации).

Например,

sdiff -w 185 file1.cfg file2.cfg

Ответ 6

Если вам нужно решить это с помощью coreutils, то принятый ответ хорош:

comm -23 <(sort file1) <(sort file2) > file3

Вы также можете использовать sd (поток diff), который не требует сортировки и замены процесса и поддерживает бесконечные потоки, например

cat file1 | sd 'cat file2' > file3

Вероятно, не так много пользы для этого примера, но все же его рассматривайте; в некоторых случаях вы не сможете использовать comm и grep -F и diff.

Здесь blogpost Я написал о различных потоках на терминале, который вводит sd.

Ответ 7

Уже много ответов, но ни один из них не идеален ИМХО. Ответ Thanatos оставляет некоторые дополнительные символы в строке, а ответ Сорпигаля требует, чтобы файлы сортировались или предварительно сортировались, что может быть неприемлемым при любых обстоятельствах.

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

Если строки не содержат "<", короткий однострочный шрифт может быть:

diff urls.txt* | grep "<" | sed 's/< //g'

но это приведет к удалению из строк всех экземпляров "<" (меньше, пробела), что не всегда нормально (например, исходный код). Самый безопасный вариант - использовать awk:

diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'

Этот однострочный шрифт разграничивает оба файла, затем отфильтровывает выходной поток diff в стиле ed, а затем удаляет конечный "<" этот diff добавляет. Это работает, даже если строки содержат некоторое число "<" самих себя.

Ответ 8

Используйте утилиту Diff и извлекайте только строки, начинающиеся с < на выходе

Ответ 9

diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt

Я попробовал почти все ответы в этой теме, но ни один из них не был завершен. После нескольких трасс над мной работало. diff даст вам разницу, но с некоторыми нежелательными специальными символами. где фактические разностные линии начинаются с ' > '. поэтому следующий шаг: строки grep начинаются с ' > ', а затем удаляются с помощью sed.

Ответ 10

Тем не менее, нет решения grep?

  • строки, которые существуют только в file2:

    grep -Fxvf file1 file2 > file3
    
  • строки, которые существуют только в file1:

    grep -Fxvf file2 file1 > file3
    
  • строки, которые существуют в обоих файлах:

    grep -Fxf file1 file2 > file3
    

Ответ 11

Вы можете использовать diff со следующим форматированием вывода:

diff --old-line-format='' --unchanged-line-format='' file1 file2

--old-line-format='', отключить вывод для file1, если строка отличалась, сравнить в file2.
--unchanged-line-format='', отключить вывод, если строки были одинаковыми.

Ответ 12

Я удивлен, что никто не упомянул diff -y, чтобы создавал параллельный вывод, например:

diff -y file1 file2 > file3

И в file3 (в разных строках есть символ | посередине):

same     same
diff_1 | diff_2