Вывести общие строки (сходства) двух текстовых файлов (противоположность diff)?


21

Diff - отличный инструмент для отображения изменений между двумя файлами. Но как отобразить сходство двух текстовых файлов (при этом игнорируя различия)?

Т.е. пример ввода:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Псевдо-вывод (что-то вроде этого):

@@ 2,3
=Hello World

Недостаточно просто отсортировать оба файла и использовать comm, потому что в этом случае информация о строке теряется.

Ответы:


24

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

diff --unchanged-group-format='@@ %dn,%df 
  %<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt

Вот что я получаю с вашими примерами данных:

$ cat a.txt 
Foo Bar
X
Hello
World
42
$ cat b.txt 
Foo Baz
Hello
World
23
$ diff --unchanged-group-format='@@ %dn,%df
%<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt
@@ 2,3
Hello
World

2
Вы можете избежать встраивания буквального перевода строки следующим образом:...%df'$'\n''%<'...
Приостановлено до дальнейшего уведомления.

1
Вы также можете сделать это следующим образом: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(Обратите внимание на двойные кавычки.)
Приостановлено до дальнейшего уведомления.

Отличный материал! Я не знал этих опций, потому что я только что посмотрел на страницу руководства diff ...
maxschlepzig

Я использую diff --version diff (GNU diffutils) 2.8.1 И получаю следующую ошибку: diff: противоречивые параметры стиля вывода diff: Попробуйте `diff --help 'для получения дополнительной информации.
Суджай

Я получаю «error: diff: конфликтующие параметры стиля вывода diff», потому что у меня определен псевдоним diff. Используйте, which diffчтобы увидеть, если это ваша проблема.
Джастинхендрик

14
grep -Fxf file1 file2

-Fозначает совпадение простых строк (не регулярных выражений), -xозначает совпадение только с целыми строками , -fозначает получение «шаблонов» (то есть строк) из файла, названного в качестве аргумента


3
Не являются -fи -Fобмен ?. По крайней мере, в моей grepверсии это так. Мне нужно обеспечить file2ввод -fаргумента, как cat file1 | grep -Fxf file2, и затем работает.
Бирей

Это не сработало для меня.
Чаминда Бандара

7

commможет быть использован. man commдля всех опций, но вы хотите использовать, comm -12 ...чтобы показать только линии, которые существуют в обоих входах.

Как уже отмечали люди, sortсначала вам нужно пройти свой вклад .


1
Хм, это работает только для общих строк с одинаковым номером в обоих файлах.
maxschlepzig

2
Кажется, что comm предназначен только для отсортированных файлов и не дает полезного вывода для сценария использования OP. Его пример: $ comm -12 ab Hello World comm: файл 1 не в порядке сортировки comm: файл 2 не в порядке сортировки
Марсель Стимберг

@maxschlepzig: вы должны отсортировать файлы перед передачей в комм.
Hemant

2
При сортировке вы избавляетесь от всей информации о положении общих линий. Вы не сортируете файлы, прежде чем сравнивать их с diff.
Марсель Стимберг

7

Я не думаю, что есть одна команда, которая делает то, что вы хотите, чтобы она делала. Вы можете попытаться объединить вывод diffс grep, хотя. Если текстовые файлы не содержат ни один из символов |, <, >следующие дает несколько полезного вывод:

$ diff --side-by-side a b | grep -n -v "[|<>]"
3:Hello                             Hello
4:World                             World

Попробуйте это:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
Пауза до дальнейшего уведомления.

это выглядит лучше - но вы должны включить <и> в grep, чтобы избавиться от добавленных строк в любом файле.
Марсель Стимберг

2

Дик Грун написал семейство инструментов для такого рода вещей:

http://dickgrune.com/Programs/similarity_tester/

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

Он упакован как similarity-testerв Debian и Ubuntu.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.