Текст книги "Linux и UNIX: программирование в shell. Руководство разработчика"
Автор книги: Дэвид Тейнсли
сообщить о нарушении
Текущая страница: 16 (всего у книги 25 страниц)
check it ls_a directory $FILENAME
# вызов функции и проверка
if [ $?=0 ]
# применение кода завершения последней команды для тестирования
then
echo "All ls OK" else
echo "Something went wrong!"
fi
Лучшим методом является использование оператора if, с помощью которого осуществляется проверка возвращаемого значения (0 или 1). Встраивание вызова функции в структуру оператора if значительно улучшает читабельность программного кода. Например:
if check_it_is_a_directory $FILENAME; then
echo "All is OK"
# действия
else
echo "Something went wrong!"
# действия
fi
Если функцию планируется использовать для отображения результатов некоторой проверки, для фиксации результата применяется подстановка. Формат, используемый для выполнения подстановки при вызове функции, будет следующим:
имя_переменной=`имя_функции`
Выводимый результат функции имя_функции присваивается переменной имя_переменной.
В последующих разделах будет продемонстрировано большое количество разнообразных функций, а также рассмотрены различные способы применения возвращаемых и выводимых значений для функции.
19.6. Файл функций
После того, как будет создано несколько регулярно используемых функций, их можно поместить в файл функций, а затем загружать этой файл в среду интерпретатора shell.
В начале файла функции должна находиться конструкция #!/bin/sh. Этому файлу можно присвоить любое имя, но все же лучше использовать какое‑либо осмысленное наименование, например functions.main.
Как только файл будет загружен интерпретатором shell, появляется возможность вызова функций из командной строки либо из сценария. Чтобы просмотреть все определенные функции, воспользуйтесь командой set. Поток вывода будет содержать все функции, которые были загружены интерпретатором shell.
Для изменения любой из ранее определенных функций сначала примените команду
unset, после чего функция будет выгружена из интерпретатора shell. В результате этого данную функцию будет невозможно вызвать из пользовательских сценариев или интерпретатора команд, хотя физического удаления функции при этом не происходит. После внесения изменений в файл функций выполните его перезагрузку. Некоторые интерпретаторы команд могут распознавать изменения, и в этом случае применение команды unset вовсе не обязательно. Однако все же в целях безопасности всегда лучше использовать данную команду при модификации функций интерпретатора shell.
19.7. Создание файла функций
А теперь создадим файл функций, включающий одну функцию. Эта функция будет загружена интерпретатором команд, протестирована, изменена, а затем повторно загружена.
Создаваемый файл функций functions.main будет содержать следующий код:
$ pg functions.main
#!/bin/sh
# functions.main
#
findit: интерфейс для базовой команды find
findit () (
#findit
if [ $# -lt 1 ]; then
echo "usage: findit file"
return 1
find / -name $1 -print
Код, приведенный выше, ранее уже упоминался в книге, но теперь он включен в состав функции. Этот код лежит в основе интерфейса для базовой команды find . Если команде не передаются аргументы, то возвращается значение 1 (что свидетельствует о возникновении ошибки). Обратите внимание, что ошибочная конструкция фактически является отображенным именем функции (если же была использована команда $0, интерпретатор команд просто возвращает сообщение sh). Причина отображения подобного сообщения заключается в том, что файл не является файлом сценария. В любом случае это сообщение не несет много информации для пользователя.
19.8. Подключение файла функций
Команда подключения файла функций имеет следующий формат:
. /путь/имя_файла
Теперь, когда файл создан, настало время загрузить его содержимое в интерпретатор команд (подключить его). Введите команду:
$. functions.main
Если в результате выполнения этой команды возвращается сообщение 'file not found' (файл не найден), попытайтесь воспользоваться следующей командой:
$ . ./functions.main
В этом случае применяется нотация <точка><пробел><косая черта><имя файлах Теперь файл должен быть загружен интерпретатором команд. Если по–прежнему возникают ошибки, убедитесь в том, что было указано полное наименование пути к файлу.
19.9. Проверка загруженных функций
Чтобы удостовериться в том, что функции были загружены интерпретатором команд, воспользуйтесь командой set, которая отображает все загруженные функции, доступные для сценария,
$ set
USER=dave
findit=()
{
if [ $# -lt 1 ]; then
echo "usage findit file";
return 1; fi; find / -name $1 -print
}
…
19.10. Вызов функций интерпретатора shell
Для вызова функции просто введите ее имя (в данном случае findit) и укажите аргумент, в роли которого может выступать файл, размещенный в системе.
$ findit groups
/usr/bin/groups
/usr/local/backups/groups.bak
19.10.1. Удаление shell–функций
Теперь настало время немного изменить функцию. Сначала функция будет удалена, в результате чего она не будет доступна интерпретатору shell. Для выполнения этой операции применяется команда unset. При вызове данной команды используется следующий формат:
unset имя_функции $ unset findit
Если вы сейчас введете команду set, функция не будет найдена.
19.10.2. Редактирование shell–функций
А теперь изменим файл fiinctions.main. Добавим в функцию цикл for, в результате чего сценарий сможет считывать более одного параметра из командной строки. Функция приобретет следующий вид:
$ pg functions.main
#!/bin/sh findit ()
{
# findit
#if [ $# -lt 1 3; then
echo "usage: findit file"
return 1 fi
for loop do
find / -name $LOOP -print done }
Снова загрузим исходный файл:
$ . ./functions.main
Используйте команду set, чтобы убедиться, что файл действительно загружен. Если интерпретатор shell корректно интерпретирует цикл for и воспринимает все требуемые параметры, на экране отобразится соответствующее сообщение.
$ set
findit=()
{
if [ $# -lt 1 ]; then
echo "usage :`basename $0` file";
return 1; fi;
for loop in "$@"; do
find / -name $LOOP -print; done }
Далее вызывается измененная функция findit. При этом поддерживаются два файла с целью осуществления поиска:
$ findit LPSO.doc passwd
/usr/local/accounts/LPSO.doc
/etc/passwd
19.10.3. Примеры функций
Теперь, когда вы получили начальные сведения о функциях, рассмотрим их практическое применение.
Сразу же стоит заметить, что использование функций позволяет сэкономить массу времени и усилий программистов. Это возможно благодаря тому, что функция является повторно применяемой.
Подтверждение ввода
Рассмотрим небольшой сценарий, который запрашивает имя и фамилию пользователя:
$ pg func2
#!/bin/sh
# func2
echo -n "What ls your first name :"
read F_NAME
echo -n "What ls your surname:"
read S_NAME
Данный сценарий предназначен для выполнения проверки значений переменных (переменным присваиваются исключительно одни символы). Выполнение этой задачи без применения функций может привести к дублированию программного кода. Функции позволяют обойтись без дублирования. Для проверки наличия одних лишь символов можно воспользоваться утилитой awk. Ниже приводится функция, которая осуществляет проверку ввода либо только прописных, либо строчных символов.
char_name()
{
#char_name
#вызов: char_name string
#назначение аргумента новой переменной
_LETTERS_ONLY=$1
#использование awk для проверки на наличие символов!
_LETTERS_ONLY=`echo $1 | awk '{if [$0~/[^a‑zA‑Z]/} print "1"}'`
if [ "$_LETTERS_ONLY" != "" ] then
# ошибки
return 1
else
# содержит только символы
return 0
fi }
Сначала переменной $1 будет присвоено более осмысленное имя. Затем применяется утилита awk, осуществляющая проверку, состоит ли переданная строка из одних литер. В результате выполнения возвращается код, включающий 1 (для символов, не являющихся литерами) и 0 – для символов–литер. Этот код присваивается переменной _LETTERS_ONLY.
Затем выполняется проверка значения переменной. Если переменной присвоено какое‑либо значение, то это свидетельствует о наличии ошибки; в случае отсутствия присвоенного значения ошибки нет. На основании результатов этой проверки формируется код возврата. Использование кода возврата позволяет сценарию фиксировать момент завершения проверки, выполняемой функцией в вызывающей части сценария.
Для проверки вывода функции можно использовать формат, применяемый для оператора if:
if char_name $F_NAME; then
echo "OK"
else
echo "ERRORS"
fi
Если происходит ошибка, можно создать другую функцию, отображающую сообщение об ошибке:
name_error ()
# name_error
# отображение сообщения об ошибке
{
echo " $@ contains errors, it must contain only letters"
}
Функция name_error будет отображать сообщения об ошибках, игнорируя при этом все некорректные записи. Применение специальной переменной $@ позволяет отображать на экране значения всех аргументов. В рассматриваемом случае будет отображено либо значение f_name, либо значение $NAME. А теперь приведем завершенный сценарий, созданный с применением функций:
$ pg func2
#!/bin/sh
char_r.ame {)
# наименование_символа
# вызов: char_name строка
# проверка на предмет того, действительно ли $1 содержит только символы a‑z.,A‑Z
{
# присвоение аргумента новой переменной
_LETTERS_ONLY=$1
_:LETTERS_ONLY=`echo $1|awk '{ if ($0~/[^a‑zA‑Z]/) print "1"}`
if [ "$_LETTERS_ONLY" != "" ]
then
# присутствуют ошибки
return 1
else
# содержит только символы
return 0
fi }
name_error()
# отображение сообщения об ошибке
{
echo " $@ contains errors, it must contain only letters"
}
while : do
echo -n "What ls your first name :"
read F_NAME
if char_name $F_NAME
then
# все OK, завершение выполнения break else
name_error $F_NAME fi done
while : do
echo -n "What ls your surname :"
read S_NAME
if char_narae $S_NAME
then
# все OK, завершение выполнения
break else
name_error $S_NAME
fi
done
Обратите внимание на то, что для обработки результатов ввода применяется цикл while. Благодаря этому на экране отображается запрос до тех пор, пока пользователь не укажет верное значение. После ввода нужного значения выполнение цикла прерывается. Конечно, при реализации работающего сценария пользователю предоставляется возможность прервать выполнение цикла. При этом также применяется соответствующее управление курсором, например при проверке наличия полей с нулевой длиной.
Ниже приведены результаты выполнения описанного сценария:
$ func2
What ls your first name: Davi2d
Davi2d contains errors, it must contain only letters
What ls your first name: David
What ls your surname: Tansley1
Tansley1 contains errors, it must contain only letters
What ls your surname: Tansley
Проблемы с конструкцией echo
В системах Linux, BSD или System V конструкция echo по–разному интерпретирует служебные символы. Создадим функцию, определяющую систему, в которой используется конструкция echo.
После того как была применена конструкция echo, командная строка может и далее отображаться на экране, ожидая ввода данных со стороны команды read.
Для реализации описанного поведения в системах Linux и BSD совместно с командой echo применяется опция -n. Ниже приводится пример конструкции echo LINUX (BSD), когда командная строка продолжает отображаться на экране до момента завершения сценария:
$ echo -n "Your паше :"
Your name : {{?}}
В System V в этом случае применяется параметр с:
$ echo "Your name :c"
Your name : []
Для отображения на экране управляющих символов в Linux также потребуется указывать опцию -e в начале оператора echo. В других системах достаточно просто воспользоваться обратной косой чертой, в результате чего интерпретатор shell будет "уведомлен" о наличии управляющего символа.
Существует два метода проверки типа используемой конструкции echo. Мы рассмотрим оба этих метода, и вы сможете выбрать один из них для дальнейшего применения.
При использовании первого метода проверка управляющего символа происходит внутри конструкции echo. Если после ввода команды echo 07 прозвучал звуковой сигнал, значит, перед нами System V. Если отображается строка " 07", значит, текущей операционной системой является Linux.
Вот первая функция, выполняющая проверку на наличие управляющих символов.
uni_prompt ()
• uni_prompt
• универсальная конструкция echo
{
if [ `echo " 07"` =" 07" ] >/dev/null 2>&1
# слышен звуковой сигнал либо отображаются символы?
then
# отображаются символы, это LINUX/BSD
echo -e -n "$@"
else
# это System V
echo "$@c"
fi }
И снова обратите внимание на применение специальной переменной $@ для отображения строки. Для вызова функции в сценарии можно использовать следующую команду:
uni_prompt " 07There goes the bell. What is your name :"
В результате выполнения этой команды выдается звуковой сигнал и отображается строка "What is your name", которая остается на экране.
Для проверки на наличие новой строки можно отобразить любой символ, используя версию команды echo c системы System V. Если символ "зависает" в конце строки, мы имеем дело с System V; если же нет, значит у нас система Linux/BSD.
Второй метод заключается в проверке того, будет ли литера Z "зависать" в конце строки. При этом используется опция с системы System V.
uni_prompt ()
#uni_prompt
#универсальная командная строка
{
if [ `echo "Zc"`="Z" ] >/dev/null 2>&1
then
# System V
echo "$@c"
else
# LINUX/BSD
echo -e -n "$@"
fi }
Для вызова данной функции из сценария применяется команда:
uni_prompt " 07 There goes the bell, What ls your name :"
Вызов любой из описанных выше функций возможен с помощью следующего кода:
uni_prompt " 07 There goes the bell, What is your name :"
read NAME
В результате мы получим:
There goes the bell, What ls your name :
Чтение одиночного символа
При создании меню одной из самых неприятных задач является необходимость нажимать клавишу [Return] после выбора каждого пункта меню либо в ответ на сообщение "нажмите любую клавишу для продолжения". В этом случае приходит на помощь команда dd, избавляющая пользователя от необходимости нажимать клавишу [Return] для отсылки ключевой последовательности.
Команда dd обычно применяется для выполнения различных преобразований и устранения проблем, связанных с хранением данных на лентах, либо при выполнении обычных задач резервирования. Данная команда также может применяться для создания файлов фиксированного размера. В следующем примере с ее помощью создается файл myfile, размер которого составляет 1 мегабайт.
dd if=/dev/zero of=myfile count=512 bs=2048
Команда dd также может интерпретировать результаты ввода с клавиатуры и использоваться для чтения символов. В данном случае ожидается появление лишь одного символа. Команда dd должна завершать выполнение после нахождения символа новой строки; этот управляющий символ появляется после нажатия пользователем клавиши [Return]. Команда dd в данном случае также посылает один символ. Перед тем как произойдет одна из описанных ситуаций, необходимо установить терминал в исходный режим. Для этого применяется команда stty. Настройки в приведенном ниже коде сохраняются перед вызовом команды dd и затем восстанавливаются после завершения выполнения команды dd.
read_a_char()
#read_a_char {
#сохранение настроек SAVEDSTTY=`stty -g`
#задание параметра терминала stty cbreak
#чтение и вывод лишь одного символа
dd if=/dev/tty bs=l count=l 2> /dev/null
# восстановление параметра терминала и настроек
stty -cbreak
stty $SAVEDSTTY }
Для вызова функции и возврата введенного символа используется подстановка команд. Вот соответствующий пример.
echo -n "Hit Any Key To Continue"
character=`read_a_char`
echo " In case you are wondering you pressed $character"
Проверка наличия каталога
Проверка наличия каталогов является весьма распространенной задачей, возникающей при копировании файлов. Приведенная ниже функция проверяет имя файла, переданное функции, что позволяет установить наличие каталога. Поскольку в этом случае используется команда return с параметром, изменяющимся в зависимости от успеха или неудачи при выполнении команды, для проверки результатов наиболее удачным является выбор конструкции if.
is_it_a_directory()
{
# is_it_a_directorу
# вызов: is_it_a_directory имя_каталога
if [ $# -lt 1 ]; then
echo "is_it_a_directory: I need an argument" return 1 fi
# это каталог ?
_DIRECTORY_NAME=$1
if [ ! -d $_DIRECTORY_NAME ]; then
# нет
return 1
else
# да
return 0
fi
}
Для вызова функции и проверки результата можно воспользоваться кодом:
echo -n "enter destination directory :"
read DIREC
if is_it_a_directory $DIREC;
then :
else
echo "$DIREC does not exist, create it now? [y..n]"
# здесь должны находится команды для создания каталога или для выхода
fi
Запрос на ввод Y или N
Многие сценарии выдают запрос на ввод подтверждения перед выполнением дальнейшей обработки. Запрос может выглядеть следующим образом:
Create a directory
Do you wish to delete this file
Run the backup now
Confirm to save a record
Этот перечень может быть достаточно длинным.
Следующая функция реализует обобщенный запрос. Пользователь указывает отображаемое сообщение, а также ответ, выбираемый по умолчанию. Ответ, выбираемый по умолчанию, используется в том случае, если пользователь просто нажал клавишу [Return]. Конструкция case применяется для перехвата ответов.
continue_prompt ()
#continue_prompt
#вызов: continue_prompt "отображаемая_строка" ответ_по_умолчанию
{
_STR=$1
_DEFAULT=$2
# проверка на предмет указания правильных параметров
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
# бесконечный цикл
while :
do
echo -n "$_STR [Y..N] [$_DEFAULT]:" read _ANS
#если пользователь нажал [Return], устанавливаются настройки
#по умолчанию и определяется возвращаемое значение,
#ниже находится пробел, а затем символ $
: ${_ANS:=S_DEFAULT}
if [ "$_ANS" = "" ]; then
case $_ANS in
Y) return 0 ;;
N) return 1 ;;
esac
fi
# пользователь что‑то выбрал
case $_ANS in
y|Y|Yes|YES)
return 0
;;
n|N|No|NO)
return 1
;;
*) echo "Answer either Y or N, default is $_DEFAULT"
;;
esac
echo $_ANS
done }
Для вызова функции можно указать отображаемое сообщение в двойных кавычках либо вызвать ее вместе с аргументом $1, либо, в крайнем случае, использовать переменную, содержащую строку. Также может передаваться ответ, заданный по умолчанию, в виде 'Y' или 'N'.
Ниже демонстрируется несколько методов, с помощью которых можно вызвать функцию continue_prompt.
if continue_prompt "Do you want to delete the var filesytem" "N"; then
echo "Are you nuts!!"
else
echo "Phew, what a good answer!"
fi
При использовании этого кода можно указывать следующий ввод:
Do you really want to delete the var filesystem [Y..N] [N] :
Phew, what a good answer!
Do you really want to delete the var filesystem [Y..N] [N] :y
Are you nuts!!
Теперь вам понятно, почему функция имеет ответ, заданный по умолчанию. Причем этот ответ может задавать сам пользователь!
Ниже приводится другой способ вызова функции:
#if continue_prompt "Do you really want to print this report" "Y"; then
lpr report
else:
fi
Функцию можно также вызвать с использованием переменной $1, содержащей строку:
if continue_prompt $1 "Y"; then
lpr report
else :
fi
Получение сведений об идентификаторе регистрации
При работе в составе большой системы может возникнуть необходимость связаться с одним из зарегистрированных пользователей. Что делать в том случае, если вы не помните имя пользователя? Часто системные администраторы наблюдают идентификаторы пользователей, блокирующих какие‑либо процессы. Для того чтобы увидеть полное имя пользователя, они должны просмотреть файл passwd с помощью команды grep. И только после этого можно связаться с пользователем, чтобы сделать ему справедливый выговор.
А сейчас мы рассмотрим функцию, которая позволит избежать просмотра файла /etc/passwd с помощью команды grep.
В тестовой системе полное имя пользователя хранится в пятом поле файла passwd; в вашей системе все может быть по–другому, поэтому, возможно, придется изменить номер поля, чтобы обеспечить соответствие с файлом passwd.
Функции передается один либо множество идентификаторов Пользователей, а функция имитирует действие команды grep по отношению к файлу passwd.
Программный код функции:
whois ()
#whois
#вызов: whois идентификатор_пользователя
{
# проверка на наличие корректных параметров
if [ $# -lt 1 ]; then
echo "whois : need user id's please"
return 1
fi
for loop do
_USER_NAME=`grep $LOOP /etc/passwd | awk -F: '(print $4}'`
if [ "$_USER_NAME"="" ]; then
echo "whois: Sorry cannot find $LOOP"
else
echo "$LOOP is $_USER_NAME" fi
done
}
Функция whois может быть вызвана следующим образом:
$ whois davs peters superman
dave ls David Tansley – admin accts
peter ls Peter Stromer -customer services
whois: Sorry cannot find superman
Использование нумерации в текстовом файле
При использовании редактора vi появляется возможность нумерации строк. Это полезно в целях отладки, но при выводе на печать некоторых файлов с номерами строк потребуется команда nl. Ниже приведена функция, имитирующая действие команды nl (выполняет нумерацию строк файла). Исходный файл при этом не перезаписывается. Вот программный код функции.
number_file ()
#number_file
#вызов: number_file имя_файла {
_FILENAME=$1
# проверка наличия корректных параметров
if [ $# -ne 1 ]; then
echo "number_flie: I need a filename to number"
return 1
fi
loop=1
while read LINE do
echo "$LOOP: $LINE" loop=`expr $LOOP + 1`
done < $_FILENAME
}
Для вызова функции number_file просто укажите имя файла, подлежащего нумерации, в качестве аргумента функции. Вызов функции может также осуществляться из среды интерпретатора shell путем указания имени файла. Например:
$ number_file myfile
Кроме того, функцию можно вызвать из сценария, воспользовавшись с этой целью предыдущим примером. Или вы можете задать оператор:
$.number_file $1
Результат выполнения функции может выглядеть следующим образом:
$ number_file /home/dave/file_listing
1: total 105
2: -rw‑r—r– 1 dave admin 0 Jun 6 20:03:DT
3: -rw‑r–r– 1 dave admin 306 May 23 16:00 LPSO. AKS
4: -rw‑r–r– 1 dave admin 306 May 23 16:00 LPSO. AKS. UC
5: -rw‑r–r– 1 dave admin 324 May 23 16:00 LPSO. MBB
6: -rw‑r–r– 1 dave admin 324 May 23 16:00 LPSO. MBB. UC
7: -rw‑r–r– 1 dave admin 315 May 23 16:00 LPSO. MKQ
Преобразование символов в прописные
Иногда возникает потребность в преобразовании строчных символов в прописные. Например, для создания каталогов в файловой системе используются прописные символы. Кроме того, при вводе данных в поля может выполняться проверка, являются ли все символы прописными.
Ниже приводится соответствующая функция. Эта функция имитирует действие команды tr:
str_to_upper ()
#str_to_upper
# вызов: str_to_upper $1
{
STR=$1
# проверка на наличие корректных параметров
if [ $# -ne 1 ]; then
echo "number_file: I need a string to convert please"
return 1
fi
echo $@ |tr '[a‑z]' '[A‑Z]'
Переменной upper присваивается строка, символы которой преобразованы в прописные символы. Обратите внимание, что снова применяется специальный символ $@ для передачи всех аргументов. Функция str_to_upper может вызываться двумя способами. Можно указать строку в сценарии следующим образом:
UPPER=`str_to_upper "documents.live"`
echo $UPPER
либо указать аргумент функции вместо строки:
UPPER=`str_to_upper $1`
echo $UPPER
В обоих примерах используется подстановка для получения результатов, возвращаемых функцией.
is_upper
Функция str_to_upper осуществляет преобразование регистра символов. Но иногда перед выполнением дальнейшей обработки необходимо только знать, содержатся ли в строке прописные символы. Это может потребоваться для записи информации в текстовое поле файла. Функция i supper выполняет именно эту задачу. Применение
оператора if В сценарии позволит определить, будет ли передаваемая строка включать прописные символы.
Программный код функции:
is_upper ()
#is_upper
#вызов: is_upper $1
{
# проверка на наличие корректных параметров
if [ $# -ne 1 ]; then
echo "is_upper: I need a string to test OK"
return 1
fi
# применение awk для проверки на наличие прописных символов
_IS_UPPER=`echo $1 | awk '{if($0~/[^A‑Z]/) print "1"}`
if [ "$_IS_UPPER" != "" ]
then
# нет, не все символы являются прописными
return 1
else
# да, все символы являются прописными
return 0
fi }
При вызове функции is_upper укажите строковый аргумент. На примере показано, как вызывается функция.
echo -n "Enter the filename :"
read FILENAME
if ls_upper $FILENAME; then
echo "Great it's upper case" else
echo "Sorry it's not upper case" fi
Для проверки наличия в строке строчных символов просто замените существующую конструкцию awk а функции is_upper и измените имя функции на is_lower.
_IS_LOWER=`echo $1 |awk '{ if ($0~/[^a‑z] /) print "1"}`
Преобразование символов строки в строчные символы
В предыдущем разделе мы рассмотрели функцию str_to_upper, а теперь речь пойдет о функции str_to_lower. Вот код самой функции:
str_to_lower ()
#str_to_lower
#вызов: str_to_lower $1
{
#проверка на наличие корректных параметров
if [ $# -ne 1 ]; then
echo "str_to_lower: I need a string to convert please"
return 1
fi
echo $@ | tr '[A‑Z]' '[a~z]'
}
Переменная lower хранит возвращенное значение строки, содержащей строчные символы. Обратите внимание на повторное использование специального параметра $@ для передачи всех аргументов. Функция str_to_lower может быть вызвана двумя способами. Во–neрвых, можно указать строку в сценарии:
LOWER=`str_to_lower "documents.live"`
echo $LOWER
Альтернативный вариант – указать аргумент для функции вместо задания строки:
LOWER=`str_to_lower $1`
echo $LOWER
Определение длины строки
Проверка результата ввода в поле является общей задачей, выполняемой сценариями. Процесс проверки может включать множество частных задач, например определение того, является ли ввод числовым или только символьным. При этом также может проверяться формат либо длина поля.
Предположим, что имеется сценарий, в рамках которого пользователь вводит данные в поле имени с помощью интерактивного экрана. В этом случае часто возникает необходимость проверить, может ли поле включать лишь определенное количество символов, например 20 символов для ввода имени персоны. Ведь пользователю не так уж трудно ввести и 50 символов в это поле. Ниже приведен код функции, осуществляющей подобную проверку. Этой функции могут быть переданы два параметра: фактическая строка и максимально возможная длина строки.
Вот сама функция:
check_length()
#check_length
#вызов: check_length строка максимальная_длина_строки
{
_STR=$1
_МАХ=$2
# проверка на наличие корректных параметров
if [ $# -ne 2 ]; then
echo "check_length: I need a string and max length the string should be" return 1
fi
# проверка длины строки
_LENGTH=`echo $_STR |awk '{print length ($0)}'`
if [ "$_LENGTH" -gt "$_MAX" ]; then
# длина строки слишком велика
return 1
else
# строка имеет обычную длину
return О
fi }
Функция check length может быть вызвана следующим образом:
$ pg test_name
#!/bin/sh
# test name
while : do
echo -n "Enter your FIRST name :"
read NAME
if check_length $NAME 10
then break.
# ничего не происходит, если все условия выполнены else
echo "The name field ls too long 10 characters max"
fi
done
Цикл продолжает выполняться до тех пор, пока данные, вводимые для переменной NAME, меньше, чем значение переменной MAX (эта переменная содержит количество разрешенных символов; в данном случае речь идет о 10 символах). Команда break позволяет завершить выполнение цикла.
При использовании приведенного выше фрагмента кода, вывод будет следующим:
$ val_max
Enter your FIRST name :Pertererrrrrrrrrrrrrrr
The name field ls too long 10 characters max
Enter your FIRST name :Peter
Команда wc также может применяться для определения длины строки, но имейте в виду следующий факт. При использовании команды wc для обработки результатов ввода с клавиатуры могут появиться проблемы. Если после ввода имени несколько раз нажать клавишу пробела, то, как правило, некоторые пробелы будут учитываться в качестве части строки. По этой причине будет определяться некорректная длина строки. Утилита awk "обрезает" конечные пробелы в строке при осуществлении ввода с клавиатуры (эта функция задана по умолчанию).
Ниже приведен пример, иллюстрирующий сказанное:
echo -n "name :"
read NAME
echo $NAME | wc -c
Результат выполнения описанного фрагмента сценария (здесь [] является пробелом):
name : Peter[][]
Функция chop
Функция chop удаляет символы в начале строки. Этой функции передается строка; пользователь указывает, сколько символов необходимо "обрезать", начиная с первого символа. Предположим, что имеется строка mydocument.doc и требуется "обрезать" часть mydocument, в результате чего функция будет возвращать только часть .doc. При этом функции chop могут быть переданы следующие параметры:
MYDOCUMENT.DOC 10
Код функции chop:
chop () # chop
# вызов: chop строка количество_обрезаемых_символов
#
STR=$1
_CHOP=$2
# подстрока awk, начинается с 0, нам потребуется прирастить ее на единицу # для отображения того, что если пользователь задал обрезание 2 символов, 2 символа будут удалены а не 1
CHOP=`expr $_CHOP + 1`
#проверка на корректность параметров
if [ $# -ne 2 ]; then
echo "check_length: I need a string and how many characters to chop"
return 1
fi
# первоначальная длина строки
# мы не можем обрезать больше символов, чем содержится в строке!!
_LENGTH=`echo $_STR | awk '{print length ($0)}'`
if [ "$_LENGTH" – lt "$_CHOP" ]; then
echo "Sorry you have asked to chop more characters than there are in the string"
return 1
fi
echo $_STR | awk '(print substr ($1, '$_CHOP')}'
}
Возвращаемая строка, которая была "обрезана", присваивается переменной chopped. Для вызова функции chop используется следующая последовательность:
CHOPPED=`chop "Honeysuckle" 5`
echo $CHOPPED
suckle
Вызов также можно осуществить другим способом:
echo -n "Enter the Filename :"
read FILENAME
CHOPPED=`chop $FILENAME 1`
# первый символ будет обрезан !
Функция months
При создании отчетов либо при отображении информации на экране часто удобным для программистов является использовании быстрого метода отображения полных наименований месяцев. Функция months в качестве аргумента использует номер месяца либо его аббревиатуру и затем возвращает полное наименование месяца.
Например, использование в качестве аргумента значения 3 либо 03 приведет к возврату значения "March". Вот описание самой функции:
months () {
# months
_MONTH=$1
# проверка на наличие корректных параметров
if [ $# -ne 1 ]; then
echo "months: I need a number 1 to 12 "