Команда echo -e "\033[31mОшибка\033[0m" в Bash выводит слово «Ошибка» красным цветом — и это самый быстрый способ проверить, поддерживает ли ваш терминал коды управления. Если вместо цветного текста вы видите набор символов вроде [31m, значит, эмулятор терминала не интерпретирует escape-последовательности, и это первое, что нужно диагностировать.
Коды управления терминалом — это невидимые служебные последовательности, которые текстовый терминал воспринимает не как обычные символы, а как команды: изменить цвет, очистить экран, переместить курсор. Они используются в скриптах, логах, консольных утилитах и при разработке CLI-приложений. В этой статье разберём, как устроены эти коды, какие из них стандартизированы, а какие зависят от конкретного эмулятора терминала.
Что такое управляющие коды и как они работают
Терминал исторически был физическим устройством — дисплеем с клавиатурой, подключённым к мейнфрейму. Чтобы программа могла не только печатать текст, но и управлять экраном, производители ввели управляющие последовательности: специальные комбинации байтов, начинающиеся с символа ESC (код 27 в таблице ASCII, шестнадцатеричное 0x1B).
Современные терминалы — это программы-эмуляторы: Windows Terminal, iTerm2, GNOME Terminal, xterm и другие. Все они в той или иной степени воспроизводят поведение классических устройств, чаще всего стандарта ANSI X3.64 и терминала DEC VT100. Когда программа выводит последовательность ESC[2J, эмулятор очищает экран, а когда получает ESC[1;32m — переключает цвет текста на ярко-зелёный.
Символ ESC можно записать в коде по-разному в зависимости от языка и оболочки:
- 🔹
\033— восьмеричная запись, работает в Bash и C; - 🔹
\x1b— шестнадцатеричная запись, привычна в Python и C; - 🔹
\e— сокращение, поддерживаемое вecho -eи многих языках; - 🔹
\u001b— Unicode-форма в Python 3 и JavaScript.
Любая ANSI-последовательность начинается с символа ESC (0x1B). Если терминал показывает коды как текст — проблема в эмуляторе или в способе вывода, а не в самих кодах.
Структура ANSI escape-последовательностей
Большинство современных кодов относятся к типу CSI (Control Sequence Introducer) и имеют вид ESC[параметры;буква. Завершающая буква определяет действие: m — оформление текста, J — очистка, H — позиционирование курсора. Параметры перечисляются через точку с запятой.
Например, последовательность ESC[1;31m расшифровывается так: параметр 1 включает жирное начертание, параметр 31 — красный цвет текста, буква m означает команду SGR (Select Graphic Rendition). Сброс всех атрибутов выполняется кодом ESC[0m — его важно добавлять после цветного фрагмента, иначе раскраска «протечёт» на весь последующий вывод.
printf '\033[1;31mВнимание!\033[0m Обычный текст\n'
⚠️ Внимание: забытый код сброса ESC[0m — самая частая причина «сломанного» терминала, когда весь текст после цветного сообщения остаётся красным или жирным. Всегда завершайте оформленный фрагмент сбросом атрибутов.
Цвета и оформление текста
Базовая палитра SGR включает восемь стандартных цветов для текста (коды 30–37) и фона (коды 40–47). Яркие варианты доступны кодами 90–97 и 100–107. Кроме цвета, SGR управляет начертанием: жирный (1), курсив (3), подчёркивание (4), инверсия (7), зачёркивание (9).
| Код | Действие | Пример последовательности |
|---|---|---|
| 0 | Сброс всех атрибутов | ESC[0m |
| 1 | Жирный / повышенная яркость | ESC[1m |
| 31 | Красный текст | ESC[31m |
| 42 | Зелёный фон | ESC[42m |
| 4 | Подчёркивание | ESC[4m |
Помимо базовой палитры, многие эмуляторы поддерживают 256-цветный режим (ESC[38;5;Nm, где N — номер цвета от 0 до 255) и true color с 24-битными значениями (ESC[38;2;R;G;Bm). Однако поддержка этих режимов зависит от конкретного терминала: перед использованием в скриптах проверьте переменную окружения TERM и документацию вашего эмулятора.
Проверить поддержку 256 цветов можно командой `tput colors` — она выведет максимальное число цветов для текущего значения TERM.
Управление курсором и экраном
Вторая большая группа кодов отвечает за перемещение курсора и очистку областей экрана. Именно они позволяют создавать динамические интерфейсы: индикаторы прогресса, обновляющиеся таблицы, мигающие статусы — всё это делается перезаписью строк вместо вывода новых.
Основные последовательности этой группы:
- 🖱️
ESC[nA/ESC[nB— курсор на n строк вверх / вниз; - 🖱️
ESC[nC/ESC[nD— курсор на n позиций вправо / влево; - 🖱️
ESC[строка;столбецH— переход в абсолютную позицию; - 🖱️
ESC[2J— очистка всего экрана,ESC[K— очистка от курсора до конца строки; - 🖱️
ESC[sиESC[u— сохранить и восстановить позицию курсора.
Классический пример — прогресс-бар, обновляющийся на одной строке. Вместо перевода строки используется возврат каретки \r и повторный вывод:
for i in $(seq 0 10 100); do
printf '\rПрогресс: %d%%' "$i"
sleep 0.2
done
printf '\n'
Обратите внимание: \r — это не CSI-последовательность, а обычный управляющий символ ASCII (код 13), однако в связке с ANSI-кодами он используется постоянно. Для скрытия курсора во время анимации применяется ESC[?25l, а для возврата видимости — ESC[?25h.
⚠️ Внимание: если скрипт со скрытым курсором завершится аварийно, курсор в терминале «пропадёт». Вернуть его можно командойprintf '\033[?25h'или полным сбросом терминала командойreset.
☑️ Безопасная работа с кодами управления
Коды управления в Windows, Linux и macOS
Исторически консоль Windows (cmd.exe) не понимала ANSI-коды — там использовался отдельный Console API. Начиная с обновлений Windows 10, в conhost появилась поддержка виртуальных терминальных последовательностей, а Windows Terminal и PowerShell работают с ними по умолчанию. Точное поведение зависит от версии системы, поэтому для кроссплатформенных скриптов проверяйте окружение.
В Python проблему совместимости решает библиотека colorama: она перехватывает ANSI-коды и конвертирует их в вызовы Windows API там, где это нужно. В Linux и macOS никакой прослойки не требуется — эмуляторы терминалов там изначально построены вокруг ANSI-стандарта.
Пример вывода цветного текста на Python без сторонних библиотек:
print('\033[1;32mУспешно\033[0m: операция завершена')
Почему в лог-файлах видны странные символы вроде [32m
Когда вывод программы перенаправляется в файл, escape-последовательности записываются туда как есть — в виде байтов. Поэтому логи, просматриваемые через less или редактор, «засоряются» кодами цветов. Решение: перед раскраской проверять, подключён ли вывод к терминалу (isatty() в Python, test -t 1 в Bash), и отключать цвета при записи в файл.
Диагностика типичных проблем
Если коды не работают, причина обычно находится в одном из трёх мест: способ вывода, эмулятор терминала или перенаправление потока. Разберём каждый сценарий.
Первый случай — коды выводятся как текст. Чаще всего виноват echo без флага -e: по умолчанию он не интерпретирует обратные слэши. Используйте echo -e или, что надёжнее, printf, который стандартизирован POSIX и ведёт себя предсказуемо в разных оболочках.
Второй случай — терминал не поддерживает последовательность. Старые или минималистичные эмуляторы (например, некоторые встроенные консоли IDE) могут игнорировать часть кодов. Проверьте значение echo $TERM: значения вроде xterm-256color означают широкую поддержку, а dumb — минимальную. Возможная причина также в устаревшей версии эмулятора — обновление часто решает проблему.
Третий случай — вывод перенаправлен. Как отмечено выше, в pipe или файл коды попадают в сыром виде. Проверка [ -t 1 ] в Bash — стандартный способ определить, подключён ли stdout к терминалу, и включать раскраску только тогда.
⚠️ Внимание: командаtputформирует последовательности с учётом базы terminfo и текущего TERM, поэтому её вывод надёжнее «зашитых» в скрипт кодов. Для переносимых скриптов предпочитайтеtput setaf 1вместо ручногоESC[31m.
Команда `infocmp` покажет, какие возможности описаны в базе terminfo для вашего значения TERM — полезно при отладке неработающих кодов.
Безопасность и ограничения
Escape-последовательности — не только инструмент оформления, но и потенциальный вектор проблем. Вредоносный текст, содержащий управляющие коды, может очистить экран, переместить курсор или подменить видимое содержимое при просмотре файла через cat. Поэтому для просмотра непроверенных файлов безопаснее использовать less с флагом -R (который контролирует интерпретацию кодов) или cat -v, показывающий управляющие символы явно.
Также помните, что стандарт не гарантирует одинакового поведения во всех эмуляторах. Одни последовательности (цвета, очистка) поддерживаются практически везде, другие — например, изменение заголовка окна через ESC]0;текст\a или скроллинг областей — реализованы не везде. Если пишете переносимый инструмент, тестируйте вывод минимум в нескольких популярных терминалах.
Надёжная формула переносимого цветного вывода: проверка isatty → использование tput или проверенных SGR-кодов → обязательный сброс ESC[0m.
Частые вопросы
Чем отличаются \033, \x1b и \e?
Это разные записи одного и того же символа ESC (десятичный код 27). Какая форма сработает, зависит от языка или утилиты: \033 и \e понимает echo -e и printf в Bash, \x1b — C и Python, \u001b — Python 3 и JavaScript.
Почему цвета не работают в скрипте через cron?
Задания cron выполняются без подключённого терминала, поэтому переменная TERM обычно не установлена, а stdout не является TTY. Коды либо не интерпретируются, либо записываются в лог как текст. Возможное решение — проверять [ -t 1 ] и отключать раскраску вне терминала.
Как вернуть терминал в норму после «глюка» с кодами?
Выполните команду reset — она переинициализирует терминал. Если пропал только курсор, достаточно printf '\033[?25h'. Если слетели цвета — printf '\033[0m'.
Можно ли использовать коды управления в prompt (PS1)?
Да, но в Bash непечатаемые последовательности нужно оборачивать в \[ и \], иначе оболочка неверно вычислит длину строки приглашения и переносы строк «поедут». Пример: PS1='\[\033[32m\]\u@\h\[\033[0m\]\$ '.
Работают ли ANSI-коды в PowerShell?
В современных версиях PowerShell и Windows Terminal — да, поддержка виртуальных терминальных последовательностей включена. В устаревших версиях консоли Windows поведение может отличаться, поэтому для старых систем сверяйтесь с документацией конкретной версии ОС.