|
Подготовлено по материалам рассылки «программирование на shell и awk» Оформление вывода в shell-сценарияхВ этой заметке будут обсуждаться:
Коварное эхоКак вы знаете, команда echo помещает в стандартный вывод свои аргументы, разделенные пробелами, и завершаемые символом перевода строки.Однако, в 70-е годы прошлого века не все было так одназначно. Существовал один филосовский вопрос. Суть его была такова: что должна делать команда echo, если ей не передали аргументов, в частности, следует ли ей выдавать пустую строку или вообще ничего не предпринимать? По этому поводу велись большие дебаты. Такие, что вдохновили Дуга МакИлроя /Doug McIlroy/ сочинить притчу, которая приведена ниже.
UNIX и эхо.
Сама природа покровительствовала UNIX и вторила ей более охотно, чем кому-либо из смертных.
Простые люди поражались ее эхом, таким оно было точным и кристально чистым. Они не могли поверить,
что ей отвечают те же леса и скалы, которые так искажают их собственные голоса. Когда один
нетерпеливый пастушок попросил UNIX: "Пусть эхо ответит ничего", и она послушно открыла рот,
эхо промолчало. "Зачем ты открываешь рот? спросил пастушок. Отныне никогда не открывай его,
если эхо должно ответить ничего!". и UNIX подчинилась.
"Но я хочу совершенного исполнения, даже если эхо отвечает ничего, потребовал другой,
обидчивый, юноша, а никакого совершенного эха не получится при закрытом рте".
Не желая обидеть никого из них, UNIX согласилась говорить разные "ничего" для нетерпеливого
и обидчивого юношей. Она называла "ничего" для обидчивого как '\n'. Однако теперь, когда она
говорила '\n', на самом деле она не произносила ничего, поэтому ей приходилось открывать
рот дважды: один раз, чтобы сказать '\n', и второй раз, чтобы не сказать ничего.
Это не понравилось обидчивому юноше, который тотчас сказал: "Для меня '\n' звучит,
как настоящее "ничего", но когда ты открываешь рот второй раз, то все портишь. Возьми второе
"ничего" назад". Услужливая UNIX согласилась отказаться от некоторых эхо и обозначила это
как '\с'. С тех пор обидчивый юноша мог услышать совершенное эхо "ничего", если он задавал
'\n' и '\с' вместе, но говорят, что он так и не услышал его, поскольку умер от излишеств
в обозначениях. [1] Хотя все настоящие реализации этой команды выдают пустую строку, это еще не значит, что проблемы закончились. Давайте их рассмотрим. Рекомендую все, о чем я буду рассказывать, проверить на практике, сидя за консолью. Так будет легче разобраться. Уже в 7-ой редакции UNIX echo распознавала флаг -n, который
подавлял вывод завершающего символа перевода строки: В System V, где команда echo умеет интерпретировать упраляющие последовательности
вида \Х, для подавления вывода завершающего символа перевода строки используют обозначение
\с. Поэтому вызвав echo с аргументом -n вы можете
получить не совсем то, что ожидали: В Linux же, echo не желает обрабатывать последовательности вида \Х: Можно воспользоваться и флагом -n, echo из Linux его понимает. Добавляет путаницы и то, что почти всегда shell имеет встроенную команду echo, поведение которой может отличаться от внешней /bin/echo. Кроме того, в системе может оказаться не одна echo, а парочка. В таком случае, второе echo обычно находится где-нибудь в районе /usr/ucb/. Из-за таких различий в реализации echo возникают определенные трудности при переносе сценариев из системы в систему. Есть ли способ их избежать? Конечно, но это уже другая история... Да будет цвет!Каким образом происходит задание цвета символов и фона, а также переключение различных режимов отображения терминала в UNIX (и во множестве других ОС)? Да также, как и в легендарные времена телетайпных терминалов посылкой на устройство отображения управляющих команд в виде esc-последовательностей (esc сокр. от англ. escape, произносится как эскейп). Такая последовательность состоит из двух или более символов, первый из которых будет esc (десятичный код равен 27, восьмеричный 033, шестнадцатеричный 0x1B; во многих программах и конфигурационных файлах обозначается как \e, \E или ^[).Перед тем как перейти к детальному рассмотрению esc-последовательностей, давайте вначале научимся вводить символ esc с клавиатуры (если вы умеете это делать, то можете переходить к выполению примеров из следующего абзаца). Чтобы ввести с клавиатуры код любой "непечатной", т. е. управляющей клавиши (функциональной, стрелки и т. п.), необходимо нажать Ctrl+V, а затем интересующую вас "кнопку". Этот прием будет работать не только в командной строке, но и в текстовом редакторе vi. Проверим на практике. Выполним команду echo "Ctrl+V,Esc[30;40m";clear
(на экране символ esc будет показан как ^[):
Если вы все сделали правильно, то
приобретайте прибор ночного видения :)! Пожалуй я не ошибусь, предположив, что у вас возникли
вопросы: Что еще могут esc-последовательности?Управлять перемещением курсора по экрану:
Очищать части экрана:
Раздвигать и сдвигать строки на экране:
Проведем испытания. Начнем с подготовки рабочего пространства. Выполните команду clear (или просто нажмите Ctrl+L). Затем более хитрую (напомню, что символы ^[ появляются в результате нажатия клавиш Ctrl+L,Esc):
tput, termcap и terminfoДовольно просто, не так ли? Однако, если вспомнить, что в UNIX для ввода/вывода можно использовать множество различных терминалов, отлищающихся и размером экрана (количество строк и символов в строке), и командами управления экраном, и кодами, которые генерируют клавиши и т. п., то возникает вопрос: как одни и те же программы умудряются корректно взаимодействовать со всем этим "зоопарком"?Наведение порядка в этом "зоосаде" обеспечивают два компонента UNIX: база данных и библиотека подпрограмм. В первом описаны поддерживаемые терминалом функции, а второй используется для выполнения запросов к базе данных. Каждый тип терминала в этой базе имеет свое название и перечень его свойств. Изначально эта информация хранилась в файле termcap (от terminal capabilities возможности терминала). C годами termcap очень вырос и в семействе AT&T юниксов превратился в базу данных terminfo. В ней, чтобы не хранить всю информацию в одном большом файле, описание каждого терминала компилируется и сохраняется в отдельном файле. Свойствами терминала могут быть:
Названия свойств стандартизированы и неизменны (почти:), а их значения наоборот изменяются в зависимости от типа терминала. В качестве примера ниже приведено несколько стандартных обозначений характеристик терминалов:
Более подробную информацию можно получить в манах по termcap и terminfo. Таким образом, когда программе нужна информация о возможностях терминала, она определяет тип используемого терминала по значению переменной окружения TERM, затем обращается к базе данных и получает соответствующее типу терминала описание, которое и использует в дальнейшем для управления вводом/выводом. Что же делать, если у вас возникло желание написать сценарий, который работал бы с любым, поддерживаемым операцинной системой, терминалом с одинаковой (или уменьшенной) функциональностью? Попробуйте воспользоваться утилитой tput. Синтаксис у нее следующий:
В качестве значения аргумента название_свойства может быть задано любое имя из списка свойств базы данных termcap и/или terminfo для терминала указанного в тип_терминала. Если этот аргумент опущен, то tput будет использовать значение переменной TERM. Для кодирования цветов используются
следующие числа (в скобках указываются цвета для режима повышенной яркости): Однако, не все так просто в нашем королевстве. Будьте готовы к тому, что в одних системах
(BSD) tput будет ожидать название_свойства в стиле termcap,
а в других (System V) в стиле terminfo. Примеры: Всем, кто хочет изучить материальную часть более предметно, рекомендую поэкспериментировать
с утилитами, которые конвертируют записи базы terminfo в termcap и наоборот.
В BSD-системах это tconv, а в Linux и юниксах ветви AT&T infocmp.
Вот вам еще примерчики: Конечно же, существует много случаев, когда использование esc-последовательностей напрямую оправдано.
Приведу в качестве примера фрагмент файла /etc/rc.status дистрибутива SuSE Linux (комментарии мои): И небольшое замечание относительно ДОСа. Помните такую ОС? Так вот, если к ней прикрутить стандартный драйвер ANSI.SYS, то все вышеперечисленные esc-последовательности будут работать и там. 1. Брайан Керниган, Роб Пайк UNIX универсальная среда программирования М.: Финансы и статистика, 1992 2. Слова из песни, которые как известно не выбросишь... |
|