Назад | Перейти на главную страницу

Как я могу заставить diff показывать только добавленные и удаленные строки? Если diff не может этого сделать, какой инструмент?

Как я могу заставить diff показывать только добавленные и удаленные строки? Если diff не может этого сделать, какой инструмент?

Попробуй комм

Другой способ взглянуть на это:

  • Показать строки, которые существуют только в файле a: (т.е. то, что было удалено из файла)

      comm -23 a b
    
  • Показать строки, которые существуют только в файле b: (т.е. что было добавлено в файл b)

      comm -13 a b
    
  • Показать строки, которые существуют только в одном или другом файле: (но не в обоих)

      comm -3 a b | sed 's/^\t//'
    

(Предупреждение: если файл a есть строки, начинающиеся с TAB, он (первый TAB) будет удален из вывода.)

Только отсортированные файлы

НОТА: Оба файла необходимо отсортировать по comm работать правильно. Если они еще не отсортированы, вам следует отсортировать их:

sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted

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

comm можете делать то, что хотите. На его странице руководства:

ОПИСАНИЕ

Сравните отсортированные файлы FILE1 и FILE2 построчно.

Без опций создать вывод с тремя столбцами. Первый столбец содержит строки, уникальные для FILE1, второй столбец содержит строки, уникальные для FILE2, а третий столбец содержит строки, общие для обоих файлов.

Эти столбцы можно подавить с помощью -1, -2 и -3 соответственно.

Пример:

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

И если вам просто нужны уникальные строки и вам все равно, в каком файле они находятся:

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

Как сказано на странице руководства, файлы необходимо предварительно отсортировать.

Чтобы показать добавления и удаления без контекста, номера строк, +, -, <,>! и т.д., вы можете использовать diff следующим образом:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

Например, даны два файла:

a.txt

Common
Common
A-ONLY
Common

b.txt

Common
B-ONLY
Common
Common

Следующая команда покажет строки, удаленные из a или добавленные к b:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

вывод:

B-ONLY
A-ONLY

Эта немного другая команда покажет строки, удаленные из a.txt:

diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt 

вывод:

A-ONLY

Наконец, эта команда покажет строки, добавленные в a.txt

diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt 

вывод

B-ONLY

Инструменты визуального сравнения объединяют два файла вместе, так что сегмент с одинаковым количеством строк, но разным содержимым будет считаться измененным сегментом. Полностью новые линии между совпадающими сегментами считаются добавленными сегментами.

Это также как sdiff работает инструмент командной строки, который показывает параллельное сравнение двух файлов в терминале. Измененные строки разделяются знаком | персонаж. Если строка существует только в файле A, в качестве символа-разделителя используется <. Если строка существует только в файле B, в качестве разделителя используется>. Если в файлах нет символов <и>, вы можете использовать это для отображения только добавленных строк:

sdiff A B | grep '[<>]'

Вот что делает diff по умолчанию ... Может, вам нужно добавить какие-то флаги, чтобы игнорировать пробелы?

diff -b -B

должен игнорировать пустые строки и разное количество пробелов.

Нет diff на самом деле не показывает различия между двумя файлами, как можно было бы подумать. Он создает последовательность команд редактирования для такого инструмента, как patch использовать для преобразования одного файла в другой.

Сложность любой попытки сделать то, что вы ищете, состоит в том, как определить, что представляет собой измененная строка по сравнению с удаленной, за которой следует добавленная. Также что делать, когда строки добавляются, удаляются и меняются рядом друг с другом.

Спасибо, сенарви, ваше решение (за которое не голосовали) на самом деле дало мне ТОЧНО то, что я хотел после долгих поисков на тоннах страниц.

Используя ваш ответ, вот что я придумал, чтобы получить список вещей, которые были изменены / добавлены / удалены. В примере используются 2 версии файла / etc / passwd и выводятся имена пользователей для соответствующих записей.

#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'

Мне часто бывает полезна именно эта форма:

diff --changed-group-format='-%<+%>' --unchanged-group-format='' f g

Пример:

printf 'a\nb\nc\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

Вывод:

-b
-c
+B
+C
-e
-f
+E
+F

Итак, он показывает старые строки с - сразу за которым следует соответствующая новая строка с +.

Если бы у нас было удаление C:

printf 'a\nb\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

это выглядит так:

-b
+B
+C
-e
-f
+E
+F

Формат задокументирован на man diff:

       --line-format=LFMT
              format all input lines with LFMT`

и:

       LTYPE is 'old', 'new', or 'unchanged'.
              GTYPE is LTYPE or 'changed'.

и:

              LFMT (only) may contain:

       %L     contents of line

       %l     contents of line, excluding any trailing newline

       [...]

Связанный вопрос: https://stackoverflow.com/questions/15384818/how-to-get-the-difference-only-additions-between-two-files-in-linux

Протестировано в Ubuntu 18.04.

Файл1:

text670_1
text067_1
text067_2

Файл2:

text04_1
text04_2
text05_1
text05_2
text067_1
text067_2
text1000_1

Использование:

diff -y file1 file2

Это показывает два столбца для файлов обзоров.

Вывод:

text670_1                           
                                  > text04_1
                                  > text04_2
                                  > text05_1
                                  > text05_2
text067_1                           text67_1
text067_2                           text67_2
                                  > text1000_1