it-roy-ru.com

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

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

107
Balualways

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

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

195
Sorpigal

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

$ diff -u file1 file2 > file3

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

44
Thanatos

Учти это:
файл 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

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

"... который содержит строки в файле file1, которых нет в файле file2."

20
Neilvert Noval

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

join -v 1 <(sort file1) <(sort file2)
7
Dennis Williamson

Пытаться

sdiff file1 file2

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

Например,

sdiff -w 185 file1.cfg file2.cfg
5
Tagar

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

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

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

cat file1 | sd 'cat file2' > file3

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

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

3
mlg

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

Я думаю, что лучший способ получить строки, которые отличаются и ничем иным (без дополнительных символов, без переупорядочения), это сочетание 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. Это работает, даже если строки содержат некоторые символы "<".

2
sergut

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

1
Capslockk

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

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

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

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

    grep -Fxf file1 file2 > file3
    
1
αғsнιη
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt

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

1
tollin jose

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

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

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

0
αғsнιη