Как я могу выполнить diff, который игнорирует все комментарии?
У меня есть большая база кода, которая была разветвлена из исходного проекта, и я пытаюсь найти все отличия от оригинала. Многие изменения в файле состоят из прокомментированного кода отладки и других замечаний. Средство сравнения/слияния GUI под названием Meld под Ubuntu может игнорировать комментарии, но только однострочные комментарии.
Есть ли другой удобный способ найти только отличия, отличные от комментариев, либо с помощью инструмента GUI или инструментов командной строки linux? В случае, если это имеет значение, код представляет собой смесь PHP и Javascript, поэтому я в первую очередь заинтересован в игнорировании //
, /* */
и #
.
Ответы
Ответ 1
Чтобы использовать визуальный diff, вы можете попробовать DiffMerge. Его набор правил и параметры обеспечивают индивидуальное поведение.
В командной строке вы можете использовать опцию --ignore-matching-lines=RE
для diff
, например:
diff -d -I '^#' -I '^ #' file1 file2
Обратите внимание, что регулярное выражение должно совпадать с соответствующей строкой в обоих файлах, и оно соответствует каждой измененной строке в hunk, чтобы работать, иначе она все равно покажет разницу.
Используйте одинарные кавычки для защиты шаблона от расширения оболочки и для выхода из зарезервированных символов с регулярным выражением (например, скобки).
Мы можем прочитать в diffutils
руководство:
Однако -I
игнорирует вставку или удаление строк, содержащих регулярное выражение, если каждая измененная строка в hunk (каждая вставка и каждое удаление) соответствует регулярному выражению.
Другими словами, для каждого неосведомляемого изменения diff
выводит полный набор изменений в его окрестности, в том числе и неосведомленные. Вы можете указать более одного регулярного выражения для игнорируемых строк, используя более одного параметра -I
. diff
пытается сопоставить каждую строку с каждым регулярным выражением, начиная с последнего.
Это поведение также хорошо объясняется armel здесь.
Ответ 2
Смотрите нашу интеллектуальную систему Differencer, которая сравнивает исходные файлы на компьютере, используя структуру langauge, а не макет в качестве руководства. Это, в частности, означает, что он игнорирует комментарии и пробелы при сравнении кода.
Существует SmartDifferencer для PHP.
Ответ 3
Вы можете сначала отфильтровать оба файла с помощью stripcmt, который удалит комментарии C и С++. Для удаления комментариев #
sed 's/#.*//'
удалит их.
Конечно, вы сначала потеряете какой-то контекст при удалении комментариев, но, с другой стороны, различия в комментариях не вызовут никаких проблем. Я думаю, что сделал бы это, как и следующее (описано для одного файла, автоматизируйте по мере необходимости):
- Если последняя версия исходной базы кода
A
и
последняя скопированная база кода B
, позвоните в
комментарии удалены для A'
и B'
(например, сохраняйте их во временные файлы во время обработки).
- Найдите общую версию исходного кода и разделите ее с текстом на
O'
(вместо этого просто используйте B'
для этого).
- Выполните трехстороннее слияние
O'
, A'
и B'
и сохраните до C'
. KDiff3 - отличный инструмент для этого.
- Теперь у вас есть изменения кода, которые вы хотите объединить, однако
C'
без комментариев, поэтому вернитесь в "обычный" режим, выполните новое слияние 3-way с A'
в качестве базы и A
и C'
. Это подберет изменения между A'
и C'
(который изменяет код, который вы хотите), в нормальную базу кода с комментариями на основе версии A
.
Рисунки деревьев версий на бумаге перед началом работы настоятельно рекомендуется получить четкое представление о том, какие версии вы хотите использовать. Но не ограничивайте себя тем, что показывает дерево, вы можете объединить любую версию и в любом направлении, если вы просто выясните, какие версии использовать.
Ответ 4
Try:
diff -I REGEXP -I REGEXP2 file1 file 2
Смотрите: Регулярное выражение в Википедии
Ниже приведены примеры регулярных выражений, которые могут привести к тому, что diff игнорирует директиву препроцессора и как стандартные стандартные блоки комментариев.
В примере:
\#*\n
/***/
//*\n
Ответ 5
gnu diff поддерживает игнорирование строк, которые соответствуют регулярному выражению:
diff --ignore-matching-lines='^#' file1 file2
и для папок:
diff -[bB]qr --ignore-matching-lines='^#' folder1/ folder2/
Это игнорирует все строки, начинающиеся С# в начале строки.
Ответ 6
diff <file1> <file2> | grep -v '^[<>]\ #'
Далек от совершенства, но он даст представление о различиях