Вопрос или проблема
Я использовал git diff, который выдает цветной вывод. Однако теперь я должен использовать обычный diff для чего-то, и он выдает много текста, который трудно читать из-за отсутствия цветов. Как сделать, чтобы diff выдавал читаемый, цветной вывод? Идеально, чтобы можно было просматривать большие файлы, пропуская их через less.
Большинство реализаций diff
не могут выводить цвет, для этого вам понадобится другая программа, такая как colordiff
. Но более новые GNU diffutils
имеют опцию --color
, так что если вы используете Linux и у вас установлена последняя версия (после v3.4, я думаю), то вы можете сделать это непосредственно с помощью diff
. Если ваш diff
не поддерживает --color
, читайте дальше.
Цвета в терминале выводятся через ANSI-коды управления, которые less по умолчанию не интерпретирует. Чтобы less
правильно отображал цвета, вам нужен переключатель -r
, или еще лучше, -R
:
colordiff -- "$file1" "$file2" | less -R
Из man less
:
-R или --RAW-CONTROL-CHARS
Как -r, но только для "цветных" ANSI последовательностей
выводится в "сыром" виде. В отличии от -r, экран
корректно отображается в большинстве случаев.
ANSI "цветные" последовательности имеют вид:
ESC [ ... m
где "..." может содержать ноль или более символов спецификации цвета.
Для отслеживания внешнего вида экрана предполагается,
что ANSI цветные коды не перемещают курсор.
Можно заставить less думать, что символы, кроме "m", могут завершать
ANSI цветные последовательности, установив переменную окружения LESSANSIENDCHARS
в список символов, которые могут завершать такую последовательность.
Также можно заставить less думать, что символы, не входящие в стандартный
набор, могут встречаться между ESC и m, установив переменную окружения
LESSANSIMIDCHARS в список символов, которые могут появляться.
Альтернативно, вы можете использовать more
, который по умолчанию правильно отображает цвета.
Если вы не можете установить внешние программы, вы можете получить тот же результат, используя более ручной подход:
diff a b |
perl -lpe 'if(/^</){$_ = "\e[1;31m$_\e[0m"}
elsif(/^>/){$_ = "\e[1;34m$_\e[0m"}'
Другие ответы здесь могут устареть. На версии coreutils 3.5 diff
действительно может выдавать цветной вывод, который по умолчанию отключен, когда stdout не является консолью.
Из man-страницы:
--color[=WHEN]
цветной вывод;WHEN
может бытьnever
,always
илиauto
(по умолчанию)
Чтобы принудительно включить цветной вывод, когда stdout является каналом, команда diff --color=always -- "$file1" "$file2" | less -R
должна сработать.
Чтобы направить цветной diff в less:
diff $file1 $file2 | colordiff | less -r
Чтобы сделать его более читаемым, ограничив отображение одним экраном:
diff -uw $file1 $file2 | colordiff | less -r
И чтобы less не отображал, если контент умещается на одном экране:
diff -uw $file1 $file2 | tee /dev/stderr | colordiff | less -r -F
Опция -F заставляет less закрываться сразу, если контент занимает менее одного экрана. Пайп на stderr используется для того, чтобы вывод был виден, даже если less не отображается.
Альтернативный (и, на мой взгляд, лучший) способ — просто использовать -X, чтобы предотвратить очистку экрана less:
diff -uw $file1 $file2 | colordiff | less -r -X -F
Это работает хорошо для меня, но может быть специфично для bash. colordiff не является встроенным, но легко устанавливается.
Я бы использовал riff:
diff "$A" "$B" | riff
Или просто это, что в фоновом режиме вызовет diff
:
riff "$A" "$B"
Riff не только указывает, какие строки изменились, но и какие части строк были изменены (см. скриншот ниже).
По умолчанию Riff использует разбиение на страницы так же, как это делает git
, так что вам не нужно беспокоиться о интеграции с просмотрщиком.
Кроме того, Riff интегрируется с git
, так что вы можете получить такой вывод от git diff
и его партнеров тоже.
Вы можете скачать его здесь: https://github.com/walles/riff/releases/
Примечание: Я сам написал riff
, поэтому, конечно, я его рекомендую :).
.
Ответ или решение
Чтобы достичь читаемого и цветного вывода командой diff
, при этом одновременно просматривать большие файлы с помощью less
, я предлагаю несколько решений с учетом вашего контекста.
Проблема
Вы замечаете, что стандартный вывод diff
трудно воспринимается из-за отсутствия цветовой индикации для различий. Цель — сделать вывод от diff
более читаемым и управляемым с помощью less
.
Решение
Использование colordiff
-
Установка colordiff: Это утилита, которая добавляет цветовые маркеры к выводу команды
diff
. Установите ее с помощью пакетного менеджера, например,apt
на Ubuntu илиbrew
на macOS:sudo apt-get install colordiff # Или brew install colordiff
-
Пайпинг вывода в less: Используйте следующий синтаксис для того, чтобы вывод оставался цветным в
less
:diff file1.txt file2.txt | colordiff | less -R
Флаг
-R
позволяетless
корректно обрабатывать ANSI-коды, обеспечивая цветной вывод без перемещения курсора.
Использование GNU diffutils
Если у вас установлена последняя версия GNU diffutils
(начиная с версии 3.4), ваша команда diff
может иметь возможность цветного вывода. Для этого выполните:
diff --color=always file1.txt file2.txt | less -R
Это обеспечит принудительный цветной вывод даже при использовании пайпов.
Ручное добавление цветов с помощью Perl
В случае, если нет возможности установить дополнительные пакеты, можно использовать Perl для добавления цветовых кодов вручную:
diff file1.txt file2.txt |
perl -lpe 'if(/^</){$_="\e[1;31m$_\e[0m"}elsif(/^>/){$_="\e[1;34m$_\e[0m"}'
Эти команды подсвечивают строки, которые были добавлены (синим цветом) или удалены (красным цветом).
Альтернативное решение с использованием riff
Если вы ищете более понятное отображение изменений на уровне символов, обратите внимание на утилиту riff
, которая делает это прозрачно и с интегрированным пейджингом:
riff file1.txt file2.txt
riff
автоматически обрабатывает вывод так, чтобы он был удобен для просмотра, даже при больших объемах данных.
Заключение
Используя одно из вышеперечисленных решений, вы улучшите читаемость вывода команды diff
, что значительно упростит анализ отличий в файлах. Integrating these tools will enhance your productivity when dealing with large volumes of data and complex code changes.