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


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


59
2017-09-25 12:47


Источник


Вам нужно лучше определить, что вы подразумеваете под добавлением и удалением. В частности, может ли строка измениться? Если да, как вы хотите, чтобы измененная строка обрабатывалась? Если вы выполняете строголинейную проверку, то изменение строки идентично удаленной старой линии и добавлению новой строки. Например, как он должен обрабатывать линию, разделенную на две части? Как изменилась две строки? 2 строки изменены? 1 строка удалена и добавлены 2 строки? Если вы не можете гарантировать, что линии никогда не будут меняться, просто добавьте и удалите, я думаю, что это обречено на провал без лучших определений. - Christopher Cashell
Я нахожу этот вопрос совершенно неясным. Но по крайней мере одна интерпретация вопроса могла быть diff A B | grep '^[<>]' - kasperd
Вы можете искать comm, - Jenny D
@ChristopherCashell, Он означает игнорировать порядок сортировки; типично общая проблема. Обычно это делается путем первой сортировки сегментов (линий) с каждой стороны, прежде чем выполнять типичный diff. - Pacerier
@Pacerier, вы в этом уверены? Или вы догадываетесь? Ничего о порядке сортировки или поиска не упоминается или не намекает в вопросе. Как бы то ни было, вопрос не ясен и может быть истолкован многими различными способами. Не зная наверняка что он спрашивает, мы делаем предположения и предлагаем решения, которые могут или не могут решить настоящую проблему. Кроме того, комментарий оригинального плаката по одному из ответов предполагает, что это не связанные с сортировкой. Это имеет значение со значением «добавлено и удалено» против «изменено». - Christopher Cashell


Ответы:


Еще один способ взглянуть на это:

Показывать строки, которые существуют только в файле a: (то есть, что было удалено из 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

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


72
2017-09-25 18:11



просто хотел добавить, что оба файла должны быть отсортированы (с учетом регистра) для этого решения для получения правильных результатов - marmor
На достаточно современных оболочках вы можете сортировать в соответствии с чем-то вроде comm -12 <(sort a) <(sort b) - Joshua Huber


comm может делать то, что вы хотите. Со своей страницы:

ОПИСАНИЕ

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

Без параметров выведите трех столбцов. Колонка 1   содержит строки, уникальные для 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

Как говорится в справочной странице, файлы должны быть отсортированы заранее.


12
2017-09-25 14:27





Чтобы показать добавления и удаления без контекста, номера строк, +, -, <,>! и т. д., вы можете использовать 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

Эта немного отличающаяся команда отображает строки, удаленные из файла .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

7
2018-01-05 06:41





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

diff -b -B

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


2
2017-09-25 13:26



Нет, он также показывает строки CHANGED (строки, имеющие характер или четыре разных). Мне нужны линии, которые существуют только слева или справа. - C. Ross
Вы можете утверждать, что разные версии файла CHANGED существуют только слева или справа. - markdrayton
Нет никакого способа, чтобы diff (или любой другой инструмент) надежно рассказывал, что такое изменение, и какая удаленная строка заменяется новой строкой. - Cian
Технически, diff обрабатывает «измененную» строку, как если бы исходная строка была удалена, и была добавлена ​​новая строка ... так что технически она показывает вам только добавленные и удаленные строки. - KFro


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

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


2
2017-09-25 15:59



Мои мысли точно. Какой процент символов в строке должен измениться, чтобы считать ее новой, а не модификацией оригинала? Технически, даже если у вас есть один общий символ, вы можете считать его «изменением» вместо удаления и вставки. - Kamil Kisiel
Прошло много времени с тех пор, как я посмотрел на diff источников, но я, кажется, помню всевозможные колебания, чтобы отслеживать, где два файла совпадают, чтобы оставаться в синхронизации, и я думаю, что есть порог для отказа от того, насколько удалены друг от друга линии. Но я не помню ни одного внутристрочного совпадения, кроме (необязательно) свернутого пробела или игнорирования случая. Или (возможно) слова к этому влиянию. В любом случае, это все о patch и «vgrep» просто приходит на прогулку. Может быть. Во вторник. - Dennis Williamson


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

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

sdiff A B | grep '[<>]'

2
2017-10-17 14:34





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

Используя ваш ответ, вот что я сделал, чтобы получить список вещей, которые были изменены / добавлены / удалены. В этом примере используются 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}'

2
2017-11-18 12:05



Обратите внимание, что поскольку разница между «строкой была изменена» и «строка удалена и другой строка была добавлена ​​ниже или выше ». Семантический. Средство для разметки на основе текста не может отделить эти случаи. В результате ваш ответ на основе sdiff не может надежно работать для всех случаев. - Mikko Rantalainen


File1:

text670_1
text067_1
text067_2

File2:

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

-1
2017-10-17 18:42