bash - цвет выходит за пределы кодов

У меня есть сценарий, который использует escape-коды для выделения текстовых совпадений в своем выводе. Все хорошо, кроме случаев, когда вывод передается по каналу less, который печатает escape-коды

например

$ echo -e "\033[31m -- Hello World! -- \033[m"
 -- Hello World! --

Трубопровод к less:

$ echo -e "\033[31m -- Hello World! -- \033[m" | less
ESC[31m -- Hello World! -- ESC[m

Мне было интересно, как другие инструменты, такие как ls, grepи т. д. в состоянии выводить в цвете, но выглядит хорошо, когда по трубопроводу less?

4 ответа

Решение

Большинство упомянутых вами инструментов вызывают функцию C isatty(), которая определяет, собирается ли соответствующий файловый дескриптор (в данном случае stdout) процесса в терминал.

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

Когда ты пишешь

grep -v "Dogs" list-of-animals | less

Вызов isatty() из grep выполняется для файлового дескриптора, ведущего к каналу, а не к вашему терминалу. Таким образом, он возвращает ноль, errno устанавливается в EINVAL или ENOTTY, а grep выводит необработанный текст, подходящий для меньшего.

Использование less -R или добавить LESS=-R в окружающую среду. Это требует, чтобы less передать некоторые escape-последовательности (например, цвет) в терминал вместо того, чтобы печатать их как обычные символы.

grep и friends определяют, есть ли выход для терминала. Когда их меньше, то они отключают окраску.

смотреть на isatty проверить, является ли вывод терминалом.

Обратите внимание, что иногда я нахожу это довольно раздражающим, потому что я хочу меньше отображать цвета:

alias less='less -SR'
alias grep='grep --color=always'

Также посмотрите на ANSIFilter для обратного: для фильтрации выходов ANSI из существующих потоков (вы также можете использовать его для создания из них HTML, RTF и, возможно, других форматов)

Если вы хотите, чтобы меньше передавало последовательности выхода цвета на терминал:

> echo -e "\033[31m -- Hello World! -- \033[m" | less -R

... или если вы хотите передать все escape-последовательности:

> echo -e "\033[31m -- Hello World! -- \033[m" | less -r

Другие вопросы по тегам