Толик Панков
hex_laden
............ .................. ................

October 2025
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Толик Панков [userpic]
Цветной текст в консоли #2

Преамбула


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



ESC-последовательности


ESC-последовательность это код, который вставляется в вызов команды echo или printf перед, после или прямо посреди текста, который мы собираемся выводить.

Синтаксис кода такой: \x1b[???m, где вместо ??? надо вставить код цвета текста, фона или стиля текста. Коды можно перечислять через точку с запятой: \x1b[???;???;???m или несколько кодов подряд: \x1b[???m\x1b[???m\x1b[???m. 1b - это код символа ASCII 27, который соответствует коду клавиши ESC (откуда и название).

Коды цвета и фона


#Название цветаКод цвета текстаКод цвета фона
0Default (По умолчанию)3949
1Black (Черный)3040
2DarkRed (Темно-красный)3141
3DarkGreen (Зеленый)3242
4DarkYellow (Темно-желтый)3343
5DarkBlue (Синий)3444
6DarkMagenta (Темно-фиолетовый)3545
7DarkCyan (Темный аквамарин)3646
8Gray (Серый)3747
9DarkGray (Темно-серый)90100
10Red (Красный)91101
11Green (Ярко-зеленый)92102
12Yellow (Желтый)93103
13Blue (Голубой)94104
14Magenta (Фиолетовый)95105
15Cyan (Аквамарин)96106
16White (Белый)97107


Код сброса: \x1b[0m - сбрасывает настройки консоли (цвет текста, фона и стиль) к значению по умолчанию.

Коды стиля текста


Код стиляСтиль текста
0Default (По умолчанию)
1Bold (Жирный)
4Understrike (Подчернкутый)
5Blinking (Мигающий), не работает, получается серый текст на темно-сером фоне
7Inversing (Инверсия), цвет фона и текста меняются местами
8Invisible (Невидимый), не работает


Тестовый скрипт


1. Проще всего покласть названия цветов, а также коды цвета и фона в массивы:

NAMES=(Default Black DarkRed DarkGreen DarkYellow DarkBlue DarkMagenta DarkCyan Gray DarkGray Red Green Yellow Blue Magenta Cyan White)
FGROUND=(39 30 31 32 33 34 35 36 37 90 91 92 93 94 95 96 97)
BGROUND=(49 40 41 42 43 44 45 46 47 100 101 102 103 104 105 106 107)


2. Создадим функцию echoc(), принимающую три параметра, цвет текста, цвет фона и стиль:

echoc() #Text, color, background, attributes
{
    ...
         Тут будет код
    ...
}


Внутри функции:

if [ -z "$2" ];then
	echo "$1" 
	return 
fi


Если второго параметра нет, просто вызываем echo и выходим из функции.

E__="\x1b[${FGROUND[$2]}m"

Второй параметр, номер кода цвета текста в массиве, формируем ESC-последовательность с ним во временную переменную.

if [ -n "$3" ];then
	E__="$E__\x1b[${BGROUND[$3]}m"
fi


Если есть третий параметр - добавляем ESC-последовательность для цвета фона.

if [ -n "$4" ];then
	E__="$E__\x1b[$4""m"
fi


Если есть четвертый - добавляем код для стиля текста (1, 4, 5, 7, 8), см. таблицу выше.

echo -e "$E__$1\x1b[0m"

Выводим текст:

-e - параметр, позволяющий команде echo обрабатывать ESC-последовательности.
$E__ - переменная, в которой сформирована ESC-последовательность.
$1 - выводимый текст.
\x1b[0m - после текста вставляем код сброса.

3. Создаем функцию echocn(), которая от функции echoc() отличается одной строчкой:

echo -e -n "$E__$1\x1b[0m"

где -n - вывести текст без перевода строки

4. Выводим в цикле названия цветов, и примеры цвета и фона:

echo -e "Foreground color:\tBackground color:"

for N in {0..16}; do
    if [ $N -eq 1 ];then #foreground
	echocn "$N - ${NAMES[$N]}" $N "16"
    else
	echocn "$N - ${NAMES[$N]}" $N
    fi
    echo -e -n "\t\t\t"
    
    if [ $N -gt 1 ];then
	echoc " ${NAMES[$N]} " 1 $N #background
    else
	echoc " ${NAMES[$N]} " 0 $N
    fi
done


5. И тестируем стили:

echo
echocn "Bold" 0 0 1; echo -n " "
echocn "Understrike" 0 0 4; echo -n " "
echocn "Blinking" 0 0 5; echo -n " "
echocn "Inversing" 0 0 7; echo -n " "
echocn "Invisible" 0 0 8; echo -n " "
echo
echo


Результат - в скрине в начале поста

Готовый скрипт


На GitHub

По мотивам


Как изменить цвет текста в терминале Linux

Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2022/10/02/tsvetnoj-tekst-v-konsoli-2/

Tags: ,
Comments

цвета можно подобрать тут - https://terminal.sexy/ (нужен жабаскрипт)

плюс есть уже довольно неплохих решений вроде gruvbox, nord, tokyo-night, etc.

свой urxvt я красил через редактирование .Xdefaults

Это заметка про то, как покрасить текст в выводе скрипта, если очень надо, а сам терминал мне дети покрасили в эмо-цвета, еле нашел, куда они скрипт запиздючили. Причем тоже ESC-последовательностью.

Да тысячи их.

Я окна вообще по необходимости включаю, ютупчик посмотреть или сюда написать, обычно у меня на рабочей машине с линухом просто консоль.

коды для яркости не входят в общепринятый стандарт VT-100, это расширение, и поддерживается далеко не всеми. один из стандартных способов увеличить яркость — включить полужирный режим: "\e[1;32m". да, это не работает для фона, стандартного метода для фона нет.

именно поэтому рекомендуется использовать библиотеку, которая умеет в termcap/terminfo, где для каждого терминала написано, что он поддерживает и как. а если вручную — то не стоит выходить за стандарт.

Т.е. нельзя так делать, мы все сделали через жопу, надо срочно удалить и пользоваться tput? В принципе, для меня и 7 цветов хватит, ну нельзя, так нельзя.

Где б такую библиотеку найти, и чтоб такое наколдовать, чтоб ее из скрипта вызывать?

просто не используй нестандарта. или если уже используешь, то чего ты стесняешься и не сразу 256 цветов тогда? выбери стул заранее, а то и ни туда, и ни сюда.

Значит, в реальных проектах использовать tput, а не ESC-коды. В принципе и его хватит.

ну с чего ты решил? ограничиться только стандартом просто: семь цветов плюс полужирный с рассчётом на то, что это давно уже яркость текста.

tput проще, укладывается в минимальный стандарт, и полужирный работает, это оставим как пример ESC-кодов.

но требует установленого ncurses. в общем и целом — никто не гарантирует его наличия.

а, вот в чем беда...

вообще, хороший тон рекомендует ещё и отключать всё это, если вывод не tty, но стандартного метода проверить такое из шелл-скрипта нет, увы.

вот в этом пичалька, экспериментировал с определением консоли, т.е что это - удаленная консоль, удаленная консоль в pytty, реальная консоль или консоль в "крысе", то ли лыжи не едут, то ли я ебанутый. Но, похоже, конкретно не едут лыжи.

вообще-то вся идея pty в том, что он неотличим от «обычного» tty. я же говорил про случай `./script.sh >dump`. в файл обычно ескейпами срать некультурно, но стандартно определить, в трубу ли мы гадим, или в tty, нет.

А, вот оно как...

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

Что-нибудь вроде "test -t 1"?
Щас глянул, вроде даже в posix оно есть.

упс. был неправ, каюсь.

А для яркости фона, случаем, нельзя ли Inversing (7) попробовать, или инверсия тоже вне стандарта?

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