Linux и UNIX: программирование в shell. Руководство разработчика
Linux и UNIX: программирование в shell. Руководство разработчика читать книгу онлайн
Данная книга является практическим руководством по программированию интерпретатора Bourne shell -cтандартного командного интерпретатора в UNIX, полностью совместимого с интерпретатором BASH shell в Linux. Книга предназначена для начинающих и опытных программистов и содержит множество полезных примеров, советов и подсказок. С ее помощью читатель сможет быстро научиться создавать shell–сценарии для реальных задач и ситуаций, возникающих в большинстве систем UNIX и Linux.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
$ 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 "[email protected]"; 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 " [email protected] contains errors, it must contain only letters"
}
Функция name_error будет отображать сообщения об ошибках, игнорируя при этом все некорректные записи. Применение специальной переменной [email protected] позволяет отображать на экране значения всех аргументов. В рассматриваемом случае будет отображено либо значение 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 " [email protected] contains errors, it must contain only letters"