Управление выводом в консоль FreeBSD

Если слово «консоль» у Вас ассоцируется с чёрным окном и серыми буковками, то эта статья для Вас! :) В данной статье описано, как использовать цвета при выводе текста, а также управлять положением курсора. В качестстве примера я приведу скрипт цветного прогрессбара, который выводит процент выполнения в виде увеличивающейся строки и текущего значения справа.

Управляющий символ ESCAPE (ASCII — 0x1B HEX, 033 OCT, 27 DEC)

Управление консолью, окном терминала и прочим хозяйством всегда начинается с вывода управляющего символа, т.н. Escape-символа. Его ASCII-код равен 27, при редактировании он обычно показывается как ^[. Однако, это непечатаемый символ и в консоли его просто так не ввести.

Чтобы обойти проблему ввода, необходимо прибегнуть к помощи тех команд, которые умеют расширять переданные им строки, заменяя код символа на сам символ. В консоле фрибсд есть, как минимум, две такие команды — встроенная echo -e в /bin/sh и утилита /usr/bin/printf. Выглядит это так:

Вывод управляющего символа Escape
# Интерпритатор /bin/sh
echo -e "\033"

# Вывод escape-символа с помощью printf
printf "\033"

После escape-символа уже идут непосредственно команды на управление терминалом (консоль, ssh-клиент и т.д.). В общем случае это выглядит примерно так:

Вывод красной надписи
# Команда выведет ярко-красную надпись «Hello» на чёрном фоне
printf "\033[1;31mHello\033[m\n"

Вот так интерпретируется строка, выведенная printf:

\033[1;31m
модификатор цвета (яркий + красный шрифт)
Hello
непосредственно надпись
\033[m
сброс модификатора цвета (возврат к стандартным настройкам)
\n
перевод строки

Модификаторы цвета

Модификатор цвета задаётся с помощью конструкции [#m, где # — номер цвета или последовательность номеров, разделённых точкой с запятой.

Аттрибуты
\033[mотмена модификаторов цвета
\033[0mотмена модификаторов цвета
\033[1mяркий
\033[4mподчёркнутый в PUTTY, яркий в FreeBSD
\033[5mсветлый в PUTTY, без эффекта в FreeBSD
\033[7mинверсия
Непонятно что
\033[12mпосле этого консоль PUTTY превратится в стадо кракозябр...
\033[21mподчёркнутый в PUTTY, без эффекта в FreeBSD
Цвет символов
\033[30mчёрный шрифт
\033[31mкрасный шрифт
\033[32mзелёный шрифт
\033[33mжёлтый шрифт в PUTTY, коричневый в FreeBSD (если не яркий)
\033[34mсиний шрифт
\033[35mмалиновый шрифт
\033[36mголубой шрифт
\033[37mсерый шрифт
Цвет фона
\033[40mчёрный фон
\033[41mкрасный фон
\033[42mзелёный фон
\033[43mжёлтый фон в PUTTY, коричневый в FreeBSD
\033[44mсиний фон
\033[45mмалиновый фон
\033[46mголубой фон
\033[47mсерый фон

Для большей наглядности я сформировал сводную таблицу цветов в файле color-freebsd.txt. Приведу скриншоты для PUTTY и FreeBSD.

Сводная таблица цветов для PUTTY

Цвета вывода консоли в PUTTY

Сводная таблица цветов для FreeBSD

Цвета вывода консоли в FreeBSD

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

Примеры цветного вывода
printf "\033[33;1mЯрко-жёлтая надпись\033[m\n"
printf "\033[1;42mЯрко-белая надпись на зелёном фоне\033[m\n"
printf "\033[1;42;7;5mЯрко-зелёная надпись на ярко-белом фоне (только для PUTTY)\033[m\n"

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

Управление курсором

\033[#Aпередвинуть курсор вверх на # позиций
\033[#Bпередвинуть курсор вниз на # позиций
\033[#Cпередвинуть курсор вправо на # позиций
\033[#Dпередвинуть курсор влево на # позиций
\033[#Eпередвинуть курсор вниз на # позиций и поставить в начало строки
\033[#Fпередвинуть курсор вверх на # позиций и поставить в начало строки
\033[#Gпередвинуть курсор в позицию # текущей строки (работает только в PUTTY)
\033[#;#Hпоместить курсор по указанным координатам
Примеры вывода текста с модификаторами положения курсора
printf "\033[20;20HHello\n"
printf "\033[1E\033[20CHello,\033[1Aworld\033[2E"

Пример реализации прогрессбара средствами консоли и /bin/sh

Подводя итог данной статьи, я приведу пример реализации графической полосы прогресса средствами /bin/sh.

Код - пример реализации полосы прогресса
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/sh

# Функция, которая выводит полосу прогресса
progressBar() {
  progress=$(( $1 * 30 / 100 ))
  bar=`printf "\33[41m% ${progress}s\33[m" ""`
  printf "\33[37D[%- 38s] %- 4s" "${bar}" "$1%"
}

# Счётчик процентов
i=0

# Надпись со смещением курсора вправо на длину полосы прогресса
printf "Format C: \33[37C"

# Цикл по процентам
while [ $i -le 100 ];
do
  progressBar $i
  i=$(( $i + 1 ))
done

# Поскольку progressBar не переводит курсор на новую строку, то делаем это сами после вывода всего прогресса
echo

В работе это выглядит примерно так:

Пример графической полосы прогресса в консоле FreeBSD

Честно скажу, что не стал заморачиваться с точными формулами расчёта координат полосы прогресса и все цифры подобрал «на глазок». Но принцип тут используется двольно простой — исходя из процента, в переменную $bar записывается графическая часть прогресса (красная полоса), которая потом выравнивается по правому краю на длину всей полосы. При этом каждый раз при выводе идёт смещение влево на длину всего прогрессбара, чтобы обеспечить статичный вид.

Заключение

Если есть вопросы или пожелания, то можете писать сюда или на форум. И удачного колоризинга консоли :)

PS: Если вдруг захотите разместить какие-либо материалы из данной статьи у себя на сайте, пожалуйста, не забудьте дать ссылку на этот сайт, как первоисточник.