355 500 произведений, 25 200 авторов.

Электронная библиотека книг » Дэвид Тейнсли » Linux и UNIX: программирование в shell. Руководство разработчика » Текст книги (страница 18)
Linux и UNIX: программирование в shell. Руководство разработчика
  • Текст добавлен: 15 октября 2016, 00:39

Текст книги "Linux и UNIX: программирование в shell. Руководство разработчика"


Автор книги: Дэвид Тейнсли



сообщить о нарушении

Текущая страница: 18 (всего у книги 25 страниц)

Ниже приводятся общие строки из потока вывода:

Название

Значение

bel

Звуковой сигнал

blink

Режим мерцания

bold

Двойная интенсивность

civis

Скрыть курсор

clear

Очистка экрана

сnorm

Отобразить курсор

cup

Перемещение курсора на экране в позицию x, у

el

Очистка до конца строки

ell

Очистка к началу строки

smso

Переход в режим отступа

rmso

Выход из режима отступа

smul

Переход в режим подчеркивания

rmul

Выход из режима подчеркивания

sc

Сохранение текущего положения курсора

rc

Восстановление последней позиции курсора

sgr0

Обычный экран

rev

Обратное видео

21.1.2. Числовой вывод

Наиболее распространенный числовой вывод:

Название

Значение

cols

Количество столбцов

it

Настройка табуляции

lines

Количество строк на экране

21.1.3. Поток вывода булевых данных

Команда tput включает незначительное количество булевых операторов.

Название

Значение

chts

Курсор трудно заметить

hs

Имеет строку статуса

21.2. Работа с командой tput

Рассмотрим наиболее распространенные разновидности команды tput, а также методы ее использования в сценариях.

21.2.1. Присвоение имен командам tput

Можно использовать поток вывода всех имен команды tput, присваивая их переменным с более осмысленными наименованиями. При этом применяется следующий формат:

имя переменной='tput name'

21.2.2. Применение булевого потока вывода

Чтобы применить булев поток вывода для команды tput, воспользуйтесь конструкцией if:

STATUS_LINE=`tput hs` if $STATUS_LINE; then

echo "your terminal has a status line"

else

echo "your terminal has NO status line"

fi

21.2.3. Использование команды tput в сценариях

В приведенном сценарии командам tput bel и cl присваиваются более значимые имена.

$ pg tput1

#!/bin/sh

BELL=`tput bel`

CLEAR=`tput cl`

echo $BELL

echo $CLEAR

В следующем сценарии изменяются несколько видеоатрибутов и происходит отображение и сокрытие курсора:

$ pg tput2

#!/bin/sh

BOLD=`tput bold`

REV=`tput rev` NORMAL=`tput sgr0` CURSOR_OFF=`'tput civis` CURSOR_ON=`tput cnorm` tput init

# сокрытие курсора, выделение текста, перестановка текста, отображение курсора

echo $CURSOR_OFF

echo "${BQLD} WELCOME TO THE PIZZA PLACE ${NORMAL}"

echo -e "n${REV} WE ARE OPEN 7 DAYS A WEEK ${NORMAL}"

echo $CURSOR_ON

21.2.4. Генерирование escape–последовательностей

Обратите внимание, что при использовании эмулятора довольно затруднительно скрыть курсор. Это обусловлено несколькими причинами:

   1. Некоторые эмуляторы не воспринимают управляющий символ, скрывающий курсор. Желательно, чтобы разработчики программного обеспечения для эмуляторов учли это замечание. В исходный код потребуется внести изменения, реализующие сокрытие курсора.

   2. Существует мнение, что некоторые более ранние версии команды tput civis не функционируют должным образом.

Управляющим символом, используемым для сокрытия курсора, является ?251

(буква l). Для возврата в исходное положение применяется символ ?25h.

Все управляющие символы выполняются с помощью escape–последовательности. Обычно за кодом клавиши [Esc] следует символ [. Затем управляющая последовательность подключает или отключает определенный атрибут терминала.

Для генерирования escape–последовательностей можно воспользоваться двумя различными методами. В таблице ниже приводятся оба метода, которые зависят от имеющейся системы. Третий метод можно применить независимо от того, используется система UNIX или Linux, поскольку управляющая последовательность реализована в составе конструкции echo. Именно третий метод и применяется в книге.

Чтобы переслать escape–последовательность и отключить курсор, используется следующий код:

Linux/BSD

echo -e "33[?251"

System V

echo "33[?251"

Обобщенный метод

echo "[?2 51"

Клавише [Esc] соответствует код 33. Символ указывает команде echo, что далее следует восьмеричное значение. Например, для вывода на экран символа @ можно применить команду:

echo "@"

Или же для вывода на экран этого символа можно воспользоваться восьмеричным значением символа, которое равно 100.

echo -e "100"

Для System V примените команду:

echo "100"

Результат будет аналогичным.

Команда clear очищает экран и устанавливает курсор в верхнем левом углу экрана. Это положение курсора обычно называется home. При работе с терминалами, относящимися к семейству VT, эту процедуру выполняет последовательность esc [2J. Данную последовательность можно отправить с помощью конструкции echo.

System V echo "33[2J"

LINUX/BSD echo -e "33[2J"

При этом следует придерживаться тех же правил, которыми руководствуются при работе с управляющими символами, помещенными в текстовые файлы. Не следует применять методику "вырезать и вставить", поскольку в этом случае будет утеряно специальное значение символов. Чтобы вставить управляющие символы, отображающие курсор, воспользуйтесь следующим кодом:

echo ' hit the key then [?25h'

Здесь даны указания о том, что следует воспользоваться комбинацией клавиш [Ctrl+V], затем нажать клавишу [Esc] и после этого ввести символы [?25h.

Если при использовании команды tput civis курсор не исчезает и при этом не запущен эмулятор, воспользуйтесь следующим небольшим сценарием. С его помощью можно скрыть либо отобразить курсор. Вы можете подробно изучить приведенную

функцию либо перевернуть пару страниц и сразу ознакомиться с результатами выполнения сценария.

$ pg cursor

#!/bin/sh

#отображение|сокрытие курсора

#отображает или скрывает курсор при работе с терминалами vt100, 200, 220, meth220

#замечание: функционирует при нормальном ttу–соединении при использовании

#некоторых win–эмуляций

#проверьте TERM env для вашего типа!

_ОРТ=$1

if [ $# -ne 1 ]; then

echo "Usage: `basename $0` cursor [on | off]"

exit 1

fi

case "$_OPT" in

on|ON|On)

# отображение курсора

ON=`echo ^[[?25h`

echo $ON

;;

off|OFF|Off)

# сокрытие курсора

OFF=`'echo ^[ [?251`

echo $OFF

;;

*)echo "Usage: cursor on | off" exit 1

;;

esac

21.2.5. Изменение положения курсора

Команду tput также можно применять для отображения курсора в произвольном месте экрана. При этом используется следующий формат:

cup r c

где r – это номер ряда (строки) в нижней части экрана, а с – номер столбца на экране.

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

xу()

(

#_R= row, _C=column

_R=$1

_C=$2

tput cup $_R $_C

}

clear

xy 1 5

echo -n "Enter your name :"

read NAME

xy 2 5

echo -n "Enter your age :"

read AGE

Конечно, желательно передавать строку для отображения; ниже приводится небольшая модификация этого сценария.

ху()

{

#_R= row, _C=column

_R-$1

_TEXT=$3

tput cup $_R $_C

echo -n $_TEXT

}

Сценарий можно вызвать следующим образом:

xy 5 10 "Enter your password :" read CODE

21.2.6. Центрирование отображаемого текста

При центрировании текста на экране нужно быть предельно внимательным. С помощью команды tput необходимо получить столбцы, затем получить значение для длины строки, исключить это значение из столбцов tput и разделить ответ на две части. В дальнейшем нужно только указать номер строки, где отобразится данная строка.

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

Введите символы, нажмите клавишу [Return], и текст отобразится в середине экрана начиная со строки 10.

echo -n "input string :"

read STR

# быстрый способ вычисления длины строки

LEN=`echo $STR | wc -с`

COLS=`tput cols`

NEW_COL=`expr ($COLS – $LEN ) / 2`

xy 10 $NEW_COL

echo $STR

Чтобы указанная функция отличалась большей гибкостью, при ее вызове можно

использовать текст и номер строки. Функция будет иметь следующий вид:

centertxt() {

_ROW=$1 _STR=$2

# быстрый способ получения длины строки

LEN=`echo $_STR | wc -c`

COLS=`tput cols`

_NEW_COL=`expr {$COLS – $LEN ) / 2`

xy $_ROW $_NEW_COL

echo $_STR

}

Чтобы вызвать функцию, следует применить команду:

centertxt 15 "THE MAIN EVENT"

или аналогичную команду, но с использованием строки в качестве аргумента:

centertxt 15 $1

21.2.7. Определение атрибутов терминала

Рассмотрим сценарий, в котором с помощью команды tput производится обращение к базе данных terminfo. С помощью некоторых команд tput отображаются управляющие коды терминала.

$ pg termput

#!/bin/sh

#termput

#инициируйте tput для терминала

tput init

clear

echo "tput <> terminfo"

infocmp -l $TERM | while read LINE

do

case $LINE in

bel*) echo "$LINE: sound the bell" ;;

blink*) echo "$LINE: begin blinking mode";;

bold*) echo "$LINE: make it bold" ;;

el*) echo "$LINE: clear to end of line" ;;

civis*) echo "$LINE: turn cursor off";;

cnorm*) echo "$LINE: turn cursor on ";;

clear*) echo "$LINE: clear the screen" ;;

kcuul*) echo "$LINE: up arrow ";;

kcubl*) echo "$LINE: left arrow ";;

kcufl*) echo "$LINE: right arrow ";;

kcudl*) echo "$LINE: down arrow ";;

esac done

Команда infocmp извлекает из файла базы данных terminfo информацию о терминале. Если нужно просмотреть файл, содержащий сведения о настройках терминала, выполните команду:

$ infocmp $TERM

Ниже с помощью сценария termput отображается поток вывода для некоторого терминала:

$ termput

tput <> terminfo

bel=^G,: sound the bell

blink=E[5m, : begin blinking mode

bold=E[1m,: make it bold

civis=E[?251,: turn cursor off

clear=E[HE[J,: clear the screen cnorm

‑E[?25h,; turn cursor on

el=E[K,: clear to end of line

ell=E[lK,: clear to end of line

kcubl=E[D,: left arrow

kcudl=E[B,: down arrow

kcufl=E[C,: right arrow

kcuul=E[A,: up arrow

21.2.8. Применение функциональных клавиш при работе со сценариями

С помощью команды cat можно обращаться к специальным клавишам ([F1], [стрелка_вверх] и т. д.). Введите команду cat -v, затем нажмите любую управляющую клавишу и просмотрите, что отобразится в нижней строке. Когда просмотр завершится, нажмите комбинацию клавиш [Ctrl+C].

В следующем примере вызывается команда cat и используются клавиши [F1] (^[OP), [F2](^[OQ) и [стрелка_вверх](^[[A).

$ cat -v

^[ОР

^[OQ

^[[А

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

В приведенном ниже сценарии распознаются клавиши [F1], [F2], а также клавиши стрелок. Пользовательские значения могут быть иными, поэтому выполните команду cat, чтобы уточнить, какие значения соответствуют управляющим клавишам терминала.

$ pg control_keys

#!/bin/sh

#управляющие_клавиши

#для вставки примените последовательность 'sequence'

uparrowkey='^[[А'

downarrowkey='^[[В'

leftarrowkey='^[[D'

rightarrowkey='^[[С'

f1key='^[OP'

f2key='^[OQ'

echo -n " Press a control key then hit return"

read KEY

case $KEY in

$uparrowkey) echo "UP arrow";;

$downarrowkey) echo "DOWN arrow";;

$leftarrowkey) echo "LEFT arrow";;

$rightarrowkey) echo "RIGHT arrow";;

$f1key) echo "F1 key";;

$f2key) echo "F2 key";;

*) echo "unknown key $key";;

esac

21.2.9. Применение различных цветов

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

Цвета переднего плана

Значение

Цвет

30

черный

31

красный

32

зеленый

33

желтый (или коричневый)

34

голубой

35

пурпурный

36

синий (циан)

37

белый (или серый)

Фоновые цвета

Значение

Цвет

40

черный

41

красный

42

зеленый

43

желтый (или коричневый)

44

голубой

45

пурпурный

46

синий (циан)

47

белый (или серый)

Для отображения цветов переднего плана и фоновых цветов применяется следующий формат:

[значение_фона; значение переднего плана m

21.2.10. Генерирование цветов

Для генерирования цвета управляющие символы встраиваются в конструкцию echo. Данный метод применяется при работе с цветным терминалом и произвольной системой. Как и в случае с управляющими символами, цвета можно генерировать с помощью escape–последовательностей, встраиваемых в конструкцию echo. Для создания черного фона с передним планом зеленого цвета воспользуйтесь командой:

Linux/BSD: echo -e "33[40;32m"

System V: echo "33[40;32m"

Обобщенный метод: echo "[40;32m"

При использовании обобщенного метода, т. е. комбинации клавиш [Ctrl+V], нажмите клавишу [Esc], затем введите символы [40;32m. Обобщенный метод и применяется далее в книге.

Возможно, лучше поместить конструкции echo, отвечающие за воспроизведение цвета, в конструкцию case, а затем оформить все это в виде функции. Ниже, приводится функция цвета case.

colour ()

(

# формат цвет_фона; цвет_переднего_планаm

case $1 in

black_green)

echo '^[[40;32m';;

black_yellow)

echo '^[[40;33m';;

black_white)

echo '^[[40;37m';;

black_cyan)

echo '^[[40;36m';;

red_yellow)

echo '^[[41;33m';;

black_blue)

echo '^[[40;34m';;

esac

}

Чтобы задать красный цвет фона и желтый цвет переднего плана, примените команду:

colour red_yellow

Для использования цветов в сценариях выполните следующие действия:

colour whatever echo something

# измените на другой цвет

colour whatever

echo something

Обычно по умолчанию в качестве цветов экрана используются черный и белый. Рассмотрим, как изменить эту установку, чтобы фоновым цветом был черный, а цветом переднего плана – зеленый. С этой целью в файл .profile достаточно добавить конструкцию echo, которая создает требуемую комбинацию.

Ниже приводится пример кода для управления экраном.

$ pg colour_scr

#!/bin/sh

# colour_scr

tput init

MYDATE=`date +%D`

colour ()

{

# формат цвет_фона; цвет_лереднего_планаm

case $1 in

black_green)

echo '^[[40;32m' ;;

black_yellow)

echo '^[[40;33m' ;;

black_white)

echo '^[[40;37m' ;;

black_cyan)

echo '^[[40;36m' ;;

black_red)

echo '^[[40;31m' ;;

esac

}

xy() #xy

   • для вызова: ху строка, столбец,"text"

   • переход к координатам ху на экране {

#_R=row, _C=column

_R=$1

_C=$2

_TEXT=S3

tput cup $_R $_C

echo -n $_TEXT

}

center()

{

center

#центрирование строки текста на экране

#для вызова: center "строка" номер_строки

_STR=$1

_ROW=$2

# неудачный способ получения длины строки

LEN=`echo $_STR | wc -с`

COLS=`tput cols`

HOLD_COL=`expr $COLS – $LEN`

NEW_COL=`expr $HOLD_COL / 2`

tput cup $_ROW $NEW_COL

echo -n $_STR

}

tput clear

colour red_yellow

xy 2 3 "USER: $LOGNAME"

colour black_cyan

center "ADD A NEW WARP DRIVE TO A STAR SHIP" 3

echo -e "ff"

center " " 4

colour black_yeliow

xy 5 1 " "

xy 7 1 "_____"

xy 21 1 " "

center "Star Date $MYDATE " 22

xy 23 1 "____ _____________"

colour black_green

xy 6 6 "Initials :"

read INIT

xy 8 14

echo -n "Security Code No: :"

read CODE

xy 10 13

echo -n "Ship's Serial No: :"

read SERIAL

xy 12 14

echo -n "Is it on the Port Side :"

read PORT

colour red_yellow

center " Save This Record [Y..N]:" 18

read ans

# восстановление обычных цветов экрана

colour black_white

Нетрудно заметить, что этот сценарий не включает методов проверки. В данном случае все нормально. Сценарий просто демонстрирует, как можно раскрасить экран.

21.2.11. Улучшение внешнего вида меню

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

1: ADD A RECORD

2: VIEW A RECORD

3: PAGE ALL RECORDS

4: CHANGE A RECORD

5: DELETE A RECORD

P: PRINT ALL RECORDS

H: Help screen

Q: Exit Menu

В сценарии обработки этого меню применяется функция read_char, поэтому пользователь не должен при выборе опций меню нажимать клавишу (Return]. Для игнорирования сигналов 2, 3 и 15 применяется команда trap (более подробно это команда обсуждается далее), поэтому пользователь может не прерывать работу с меню.

Меню также имеет возможности по управлению доступом. Пользователи, обладающие определенными привилегиями, могут вносить изменения в записи или удалять их. Остальным пользователям разрешается только добавлять записи, просматривать их и выводить на экран. Список действительных пользователей с указанием уровней доступа находится в файле priv.user.

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

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

Ниже приводится файл priv.user, содержащий имена пользователей, которые могут или не могут удалять записи и вносить в них изменения. Из приведенного текста видно, что пользователи root, dave и matty не имеют права вносить изменения в файлы баз данных, а пользователи peter и louise располагают этим правом.

$ pg priv.user

#файл доступа priv.user для меню apps

#его изменение является рискованным !!!!

#формат реализуют записи USER AMEND/DELETE

#например, запись "root yes" означает, что пользователь root может

#обновлять или удалять записи

#запись "dave no" означает, что пользователь dave не может обновлять или удалять записи

root no

dave no

peter yes

louise yes

matty no

Чтобы проверить права доступа пользователей, сначала просмотрим файл. При этом игнорируются строки комментария, а все другие строки перенаправляются в файл temp.

user_level()

(

while read LINE

do

case $LINE in

#*);;

*) echo $LINE >>$HOLD1 ;;

esac done < $USER_LEVELS

FOUND=false

while read MENU_USER PRIV

do

if [ "$MENU_USER"="$USER" ]; then

FOUND=true

case $PRIV in

yes|YES) return 0 ;;

no|NO) return 1 ;;

esac

else

continue

fi

done <$HOLD1

if [ "$FOUND"="false" ]; then

echo "Sorry $USER you have not been authorised to use this menu"

exit 1

fi

На следующем этапе просматривается заново отформатированный файл. Переменной FOUND присваивается значение "ложь". Теперь файл temp включает только описание имен и прав доступа; именам пользователей и правам доступа назначаются переменные. Чтобы уточнить, соответствует ли имя в файле значению user, производится проверка; значение user берется из команды whoami, расположенной в начале сценария. Если совпадение не найдено, выполняется проверка с помощью конструкции else, и с помощью команды continue обработка продолжается на следующей итерации.

Этот процесс длится до тех пор, пока все имена пользователей не будут просмотрены. При этом имя пользователя сравнивается со значением переменной USER. Если при просмотре всего файла совпадение не установлено, конструкция test в конце программного кода проверяет значение переменной FOUND. Если значением переменной является "ложь", пользователю отказывается в дальнейшей работе.

Если в процессе выполнения цикла while устанавливается искомое соответствие, переменной found присваивается значение "истина". Затем с помощью конструкции case выбираются права доступа. При этом возвращается 1 для обычных прав доступа либо 0 – для расширенных прав доступа.

Когда пользователь приступает к внесению изменений в запись или к удалению записи, выполняется проверка. Этот процесс основывается на коде возврата функции, описанном выше. В приведенном сценарии либо выполняется сортировка файла passwd, либо отображается каталог:

if user_level; then

sort /etc/passwd

else

restrict

fi

Функция restrict просто выводит на экран сообщение о нарушении прав доступа.

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

Чтобы выйти из меню, пользователь выбирает пункт q или Q, в результате чего вызывается функция для очистки экрана. Когда пользователь завершает работу с любым обширным сценарием, очень удобно в этом случае воспользоваться функцией. Это позволяет увеличить количество команд, выполняемых пользователем при завершении работы. Кроме того, значительно улучшается читабельность кода.

Ниже приводится соответствующий сценарий.

$ pg menu2

#!/bin/sh

#menu2

#СЦЕНАРИЙ ГЛАВНОГО МЕНЮ

#игнорирование CTRL‑C и прерывания QUIT

trap "" 2 3 15

MYDATE=`date +%d/%m/%Y`

THIS_HOST=`hostname -s`

USER=`whoami`

#файл, описывающий права доступа пользователя USER_LEVELS=priv.user

#файл для хранения

HOLDl=holdl.$$

#функция задания цвета

colour ()

{

# формат цвет_фона; цвет_переднего_планаm

case $1 in

black_green)

echo '^[[40;32m' ;;

black yellow)

echo '^[[40;33m' ;;

black_white)

echo '^[[40;37m' ;;

Ьlаск_суап)

echo '^[[40;36m' ;;

red_yellow)

echo '^[[41;33m' ;;

esac

}

# чтение значения клавиши

get_char()

(

#get_char

#сохранение текущих установок stty SAVEDSTTY=`stty -g`

stty cbreak

dd if=/dev/tty bs=1 count=1 2> /dev/null

stty -cbreak

# восстановление установок stty

stty $SAVEDSTTY

}

# отображение или сокрытие курсора

cursor ()

{

#cursor

#отображение/сокрытие курсора

_OPT=$1

case $_OPT in

on) echo '^[[?25h';;

off) echo '^[[?251';;

*) return 1;;

esac }

# проверка прав доступа пользователя

restrict ()

{

colour red_yellow

echo -e -n "nn07Sorry you are not authorised to use this function"

colour black_green

}

user_level () {

# user level

# просмотр файла priv.user

while read LINE

do

case $LINE in

# игнорирование комментариев

#*);;

*) echo $LINE >> $HOLD1 ;;

esac

done < $USER_LEVELS

FOUND=false

while read MENU_USER PRIV

do

if [ "$MENU_USER"="$USER" ]; then

FOUND=true

case $PRIV in

yes|YES)

return 0 ;;

no|NO)

return 1 ;;

esac

else

# соответствие не найдено, чтение следующей записи

continue

fi

done <$HOLD1

if [ "$FOUND"="false" ]; then

echo "Sorry $USER you have not been authorised to use this menu"

exit 1

fi

}

# вызывается, если пользователь выполняет выход из программы

my_exit()

{

#my_exit

#вызывается, если пользователь выбирает выход из сценария!

colour black_white

cursor on

rm *.$$

exit 0

}

tput init

# отображение на экране уровня доступа пользователя

if user_level; then

ACCESS="Access Mode ls High"

else

ACCES3="Access Mode ls Normal"

fi

tput init

while :

do

tput clear

colour black_green

cat < MAYDAY

$ACCESS

MAYDAY

colour black_cyan

echo -e -n "tYour Choice [1,2,3,4,5,P, H,Q] >"

@ read CHOICE

CHOICE=`get_char`

case $CHOICE in

1) ls ;;

2) vi ;;

3) who ;;

if userlevel; then

ls -l |wc

else

restrict

fi ;;

5)

if userlevel; then

sort /etc/passwd

else

restrict

fi ;;

esac

echo -e -n "tHit the return key to continue"

read DUMMY

done

Подобное меню можно вызвать с помощью команды exec (из файла profile). Пользователи не могут изменить эту последовательность действий. Такой подход распространен в случае с пользователями, работающими только с приложениями UNIX или Linux и не использующими возможности интерпретатора shell.

21.3. Заключение

Команда tput позволяет значительно улучшить контроль со стороны пользователей за выполнением сценариев. Применение цветов улучшает внешний вид меню. Будьте осторожны при использовании гаммы цветов; цвета могут быть привлекательны для вас, но не отвечать вкусам пользователя, вынужденного применять сценарий. Работа со сценариями значительно облегчается при использовании управляющих символов. Это особенно проявляется в случае, когда пользователи осуществляют ввод информации путем выбора назначенных клавиш.

ГЛАВА 22

Создание экранного ввода

Когда речь идет об экранном вводе, или вводе данных, подразумевают ввод информации (в нашем случае с помощью клавиатуры), а затем – проверку достоверности введенных данных. Если данные удовлетворяют неким критериям, они сохраняются.

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

В главе обсуждаются следующие темы:

   • проверка достоверности вводимых данных;

   • добавление, удаление, обновление записей и их просмотр;

   • сценарии, выполняющие обновление файлов.

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

Рассмотрим отдельные задачи, из которых складывается общая система по обновлению файлов, включающая такие функции, как добавление, удаление, обновление и просмотр записей. В результате создается система хранения актуальной информации О сотрудниках. Записи в файле DBFILE содержат следующие сведения:


Поле

Длина

Разрешен ввод следующей информации

Описание

Staff number

10

Числовая

Номер служащего по штатному расписанию

First name

20

Символьная

Имя служащего

Second name

20

Символьная

Фамилия служащего

Department

Accounts

Отдел, где работает служащий

IT

Services

Sales

Claims

Поля разделяются двоеточием (:). Например:

:::

Каждое задание представляет собой завершенный сценарий. Небольшие части кода дублируются в некоторых представленных ниже сценариях. И это не случайно, поскольку настоящая глава посвящена описанию системы обновления данных. Когда я впервые приступил к написанию сценариев, то обнаружил явный дефицит документации, написанной простым и понятным языком. Особенно недостает описаний совместного использования базы данных и системы по обновлению файлов.

Для связи различных заданий реальный сценарий должен иметь соответствующее меню или модуль. Чаще всего для этой цели используется оболочка функций, содержащихся в файле, совместно с каким‑либо меню сценария. Каждый сценарий включает команду trap; благодаря ее использованию игнорируются сигналы 2, 3 и 15.

22.1. Добавление записей

При добавлении записи в файл выполняются следующие задачи:

   1. Подтверждение вводимых данных.

   2. Внесение записи в файл.

Сначала необходимо связать вместе некоторые функции. Тогда можно узнать, являются ли поля числовыми или символьными, а также уточнить их размеры. В этом и состоит подтверждение вводимых данных. Подтверждение данных осуществляется при добавлении записей, а также при их обновлении. К счастью, некоторые из' требуемых функций уже имеются в вашем арсенале.

Функция для проверки длины строки:

length_check()

{

# length_check

# $1=строка, $2= длина строки не превышает этого значения

_STR=$1

_МАХ=$2

_LENGTH=`echo $_STR | awk '{print length ($0) }"`

if [ "$_LENGTH" -gt "$_MAX" ]; then

return 1 else

return 0 fi }

Функция, выполняющая проверку наличия в строке исключительно числовых данных:

a_number ()

   • a_number

   • $1=string {

_NUM=$1

_NUM=`echo $1 awk '{if($0~/[^0-9]/) print "1")'`

if [ "$_NUM" != "" ]

then

return 1

else

return 0

fi

}

Функция, позволяющая определить, состоит ли строжа исключительно из одних символов:

characters()

#characters

#$1=string

{

_LETTERS_ONLY=$1

_LETTERS_ONLY=`echo $1|awk '{if($0~/[^a‑zA‑Z]/) print "l"}'`

if [ "$_LETTERS_ONLY" != "" ]

then

return 1 else

return 0 fi

}

При просмотре полей можно просто вызвать необходимую функцию и затем проверить коды возврата.

Чтобы сообщения находились на экране до тех пор, пока пользователь не нажмет на клавишу для их удаления, нужно воспользоваться командным приглашением. Следующая функция реализует командное приглашение read_a_char.

continue_promptYN() {

# continue_prompt

echo -n "Hit any key to continue.."

DUMMY=`read_a_char`

}

Когда вводятся данные пользователя, содержащие номер служащего, нужно убедиться, что ранее подобная информация не вводилась. Поле должно быть уникальным. Существует несколько способов для выполнения этой задачи; в данном случае применяется команда grep. С помощью команды grep выполняется поиск номера служащего, который содержится в строке _CODE. Если утилита awk не возвращает какого‑либо значения, то дублирующиеся значения отсутствуют и функция завершает выполнение с кодом возврата 0. Ниже приводится код этой функции. (Обратите внимание, что для нахождения точного соответствия в команде grep используется выражение "$_CODE>". Двойные кавычки служат для сохранения значения переменной; при использовании одинарных кавычек ничего возвращаться не будет.)

check_duplicate() {

#check_duplicate

#проверка дубликата номера служащего

_CODE=$1

MATCH="grep "$_CODE>" $DBFILE"

echo $_CODE

if [ "$MATCH"="" ]; then

return 0 # нет дублирования

else

return 1 # дубликат найден

fi

}

Ниже приводится часть программного кода, выполняющая проверку номера

служащего. Функционирование этого программного кода объясняется дальше.

while : do

echo -n "Employee Staff Number :"

read NUM

# проверка вводимых данных

if [ "$NUM" != "" ]; then

if a_number $NUM; then

# номер OK

NUM_PASS=0

else

NUM_PASS=1

fi

if length_check $NUM 10; then

# длина OK

LEN_PASS=0

else

LEN_PASS=1

fi

# проверка наличия дубликатов…

if check_duplicate $NUM; then

# нет дубликатов

DUPLICATED=0

else

DUPLICATED=1

echo "Staff Number: There ls already an employee with this number"

continue_prompt

fi

# проверка значений всех трех переменных; все они должны выполняться

if [ "$LEN_PASS"="0" -a "$NUM_PASS"="0" -a "$DUPLICATE"="0" ]

then

break

else

echo "Staff Number: Non‑Numeric or Too Many Numbers In Field" continue_prompt

fi

else

echo "Staff Number: No Input Detected, This Field Requires a Number" continue_prompt

fi

done

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

После просмотра номера служащего проверяется, содержатся ли в поле некоторые данные:

if [ "$NUM" != "" ]

Если поле не содержит данные для ввода, не выполняется часть then конструкции if. В части else, которая завершает код подтверждения поля, отображается следующее сообщение:

Staff Number: No Input Detected, This Field Requires a Number

Часть then производит все необходимые проверки правильности вводимых данных. При условии, что имеются вводные данные, вызывается функция a_number. Эта функция проверяет, содержит ли передаваемая строка числовые данные; если это так, функция возвращает значение 0, в противном случае возвращается значение 1, На базе возвращаемых значений флагу num_pass присваивается либо значение о (успешный возврат – наличие строки из чисел), либо значение 1 (неудачный возврат -cтрока не является числовой).

Затем вызывается функция length check. Эта функция передает не только строку, но и максимальное число символов, содержащихся в строке. В данном случае передается десять символов. Если количество символов меньше или равно максимальной величине, отображается значение 0; иначе возвращается значение 1. Флаг len_PASS принимает либо значение 0 (в случае успешного возврата, когда длина строки не превышает максимального значения), либо значение 1 (при неудачном возврате, если получена строка, длина которой равна максимальному значению).


    Ваша оценка произведения:

Популярные книги за неделю