Как я могу выполнить diff, который игнорирует все комментарии? - PullRequest
16 голосов
/ 21 сентября 2011

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

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

Ответы [ 6 ]

4 голосов
/ 22 марта 2015

Чтобы использовать визуальные различия, вы можете попробовать DiffMerge . Его наборы правил и опций обеспечивают индивидуальное поведение.

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

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

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

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

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

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

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

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

1 голос
/ 23 сентября 2011

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

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

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

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

1 голос
/ 22 сентября 2011

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

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

0 голосов
/ 23 октября 2014
diff <file1> <file2> | grep -v '^[<>]\ #'

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

0 голосов
/ 12 марта 2013

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

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

и для папок:

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

При этом игнорируются все строки, начинающиеся с # в начале строки.

0 голосов
/ 21 сентября 2011

Попробуйте:

diff -I REGEXP -I REGEXP2 file1 file 2

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

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

Например:

\#*\n
/***/
//*\n
...