Как я могу заставить 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