Как я могу выполнить сравнение, игнорирующее все комментарии?

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

Есть ли другой удобный способ найти только отличия без комментариев, используя инструмент с графическим интерфейсом или инструменты командной строки Linux? Если это имеет значение, код представляет собой смесь PHP и Javascript, поэтому меня в первую очередь интересует игнорирование //, /* */ и #.


person Matt V.    schedule 21.09.2011    source источник


Ответы (7)


Чтобы использовать визуальное различие, вы можете попробовать Meld или DiffMerge.

DiffMerge

Его наборы правил и параметры обеспечивают индивидуальное поведение.

GNU diffutils

С точки зрения командной строки вы можете использовать параметр --ignore-matching-lines=RE для diff, например:

diff -d -I '^#' -I '^ #' file1 file2

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

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

Мы можем прочитать в руководстве diffutils :

Однако -I игнорирует вставку или удаление строк, содержащих регулярное выражение, только если каждая измененная строка в блоке (каждая вставка и каждое удаление) соответствует регулярному выражению.

Другими словами, для каждого неотрицательного изменения diff печатает полный набор изменений в его окрестности, включая игнорируемые. Вы можете указать более одного регулярного выражения для игнорируемых строк, используя более одного параметра -I. diff пытается сопоставить каждую строку с каждым регулярным выражением, начиная с последнего заданного.

Это поведение также хорошо объясняется здесь, armel.


Смотрите также:

В качестве альтернативы проверьте другие приложения для сравнения, например:

person kenorb    schedule 21.03.2015
comment
Интересно, как я могу настроить DiffMerge, чтобы игнорировать строки комментариев для кода C / C ++. Особенно при сравнении папок. - person Anton Kukoba; 24.07.2019

Вы можете отфильтровать оба файла с помощью stripcmt, которая сначала удалить комментарии C и C ++. Если вы удалите # комментарии, sed 's/#.*//' удалит их.

Конечно, вы потеряете некоторый контекст при первом удалении комментариев, но, с другой стороны, различия в комментариях не вызовут никаких проблем. Думаю, я бы сделал это следующим образом (описано для одного файла, при необходимости автоматизируйте):

  1. Если последней версией исходной базы кода является A, а самой последней из скопированной базы кода является B, давайте вызовем версии с удаленными комментариями для A' и B' (например, сохраните их во временные файлы во время обработки).
  2. Найдите какую-нибудь общую версию происхождения и удалите комментарии из нее в O' (в качестве альтернативы просто повторно используйте для этого B').
  3. Выполните 3-стороннее объединение O', A' и B' и сохраните в C'. KDiff3 - отличный инструмент для этого.
  4. Теперь у вас есть изменения кода, которые вы хотите объединить, однако C' без комментариев, поэтому вернитесь в «нормальный» режим, выполните новое трехстороннее слияние с A' в качестве основы и A и C'. При этом изменения между A' и C' (то есть код меняет то, что вы хотите) перейдут в нормальную базу кода с комментариями, основанными на версии A.

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

person hlovdal    schedule 22.09.2011

diff <file1> <file2> | grep -v '^[<>]\ #'

Далеко не идеален, но даст представление о различиях

person Vadym Tyemirov    schedule 23.10.2014

См. Нашу линейку инструментов Smart Differencer, которые сравнивают исходные файлы на компьютерном языке с использованием языковой структуры, а не макет в качестве ориентира. В частности, это означает, что при сравнении кода игнорируются комментарии и пробелы.

Существует SmartDifferencer для PHP.

person Ira Baxter    schedule 21.09.2011
comment
PS: Мэтт, мы тоже в Остине. - person Ira Baxter; 22.09.2011
comment
@TomasTintera: Хм, мы думаем, что SmartDiff довольно умен. Не могли бы вы уточнить, какой язык (PHP? Java? ...) Smart Diff вы пробовали, и обстоятельства / фактические обстоятельства, которые не дали того, чего вы ожидали, а именно того, что вы ожидали? (Вы можете отправить пример на [email protected], и мы его рассмотрим). - person Ira Baxter; 18.07.2017
comment
@TomasTintera: Я заметил, что OP искал инструмент, который бы игнорировал комментарии (изменения). SmartDiff делает то, что просил OP. - person Ira Baxter; 18.07.2017
comment
Конечно. Спасибо за напоминание. Мой комментарий удален, так как он относится к другому вопросу и ответу. - person Tomas Tintera; 20.07.2017

gnu diff поддерживает игнорирование строк, соответствующих регулярному выражению:

diff --ignore-matching-lines='^#' file1 file2

и для папок:

diff -[bB]qr --ignore-matching-lines='^#' folder1/ folder2/

Это приведет к игнорированию всех строк, которые начинаются с символа # в начале строки.

person StackUnderflow    schedule 12.03.2013
comment
This would ignore all lines which start with a # at the line beginning. Это не правда. --ignore-matching-lines ведет себя иначе. - person Avio; 31.07.2013

Я попробовал: diff file1 file2 и diff -d -I ^#.\* file1 file2, и результат был одинаковым в обоих случаях - включил комментарии;

однако diff -u file1 file2 | grep -v '^ \|^.#\|^.$' дает то, что мне нужно: только реальные различия, без комментариев, без пустых строк. ;)

person Jerzy Tarasiuk    schedule 14.12.2019

Пытаться:

diff -I REGEXP -I REGEXP2 file1 file 2

См. Регулярное выражение в Википедии

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

Например:

\#*\n
/***/
//*\n
person awiebe    schedule 21.09.2011
comment
Нет, --ignore-matching-lines не удаляет комментарии полностью. - person Avio; 31.07.2013