Понимание и написание функций в сценариях оболочки. Часть VI
Функции играют важную роль в любом языке программирования. Как и во многих реальных языках программирования, в bash есть функции, реализация которых ограничена.
Что такое функции?
В программировании функции — это именованные разделы программы, выполняющие определенную задачу. В этом смысле функция — это тип процедуры или процедуры. При вызове функции программа покидает текущий раздел кода и начинает выполнять первую строку внутри функции. Всякий раз, когда есть повторяющийся код или задача повторяется, рассмотрите возможность использования вместо нее функции.
Например, рассмотрим случай, когда нам нужно найти факториал числа на нескольких этапах конкретной программы. Вместо того, чтобы каждый раз писать весь код (для вычисления факториала), мы можем написать ту часть кода, которая вычисляет факториал один раз внутри блока и повторно использовать его несколько раз.
Зачем мы пишем функции?
- Это помогает нам повторно использовать код.
- Улучшите читабельность программы.
- Эффективное использование переменных внутри программы.
- Позволяет нам протестировать программу по частям.
- Отображает программу в виде набора подэтапов.
Функции в сценариях оболочки
Общий синтаксис написания функций в сценарии оболочки включает следующие способы.
function func_name {
. . .
commands
. . .
}
or
func_name ( ) {
. . .
commands
. . .
}
Opening curly braces can also be used in the second line as well.
func_name ( )
{
. . .
commands
. . .
}
Вы всегда можете писать допустимые команды внутри этих функциональных блоков, как мы обычно делаем в сценариях оболочки. Теперь попробуем написать один простой скрипт с небольшой функцией внутри него.
#!/bin/bash
call_echo ( ) {
echo ‘This is inside function’
}
op=$1
if [ $# -ne 1 ]; then
echo "Usage: $0 <1/0>"
else
if [ $1 = 0 ] ; then
echo ‘This is outside function’
elif [ $1 = 1 ] ; then
call_echo
else
echo ‘Invalid argument’
fi
fi
exit 0
Определение функции должно предшествовать первому ее вызову. Нет ничего лучше «объявления функции» перед ее вызовом. И мы всегда можем вкладывать функции внутрь функций.
Примечание. Написание пустых функций всегда приводит к синтаксическим ошибкам.
Когда одна и та же функция определяется несколько раз, вызывается окончательная версия. Давайте возьмем пример.
#!/bin/bash
func_same ( ) {
echo ‘First definition’
}
func_same ( ) {
echo ‘Second definition’
}
func_same
exit 0
Функции, принимающие параметры и возвращающие значения
Давайте углубимся и рассмотрим функции, принимающие параметры и возвращающие значения. Чтобы вернуть значение из функции, мы используем встроенную оболочку return. Синтаксис следующий.
func_name ( ) {
. . .
commands
. . .
return $ret_val
}
Аналогично мы можем передавать аргументы функциям, разделенные пробелами, как показано ниже.
func_name $arg_1 $arg_2 $arg_3
Внутри функции мы можем получить доступ к аргументам в следующем порядке: $1, $2, $3 и так далее. Посмотрите на следующий пример сценария, чтобы найти максимум два целых числа, используя функцию, чтобы добавить большей ясности.
#!/bin/bash
USG_ERR=7
max_two ( ) {
if [ "$1" -eq "$2" ] ; then
echo 'Equal'
exit 0
elif [ "$1" -gt "$2" ] ; then
echo $1
else
echo $2
fi
}
err_str ( ) {
echo "Usage: $0 <number1> <number2>"
exit $USG_ERR
}
NUM_1=$1
NUM_2=$2
x
if [ $# -ne 2 ] ; then
err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then
max_two $NUM_1 $NUM_2
else
err_str
fi
else
err_str
fi
exit 0
Вышеупомянутое выглядит немного сложным, но если мы прочитаем строки, все будет просто. Первые вложенные строки if-else if для целей проверки, т. е. для проверки количества и типа аргументов с помощью регулярных выражений. После этого мы вызываем функцию с двумя аргументами командной строки и выводим туда сам результат. Это связано с тем, что мы не можем возвращать из функции большие целые числа. Другой способ обойти эту проблему — использовать глобальные переменные для хранения результата внутри функции. Сценарий ниже объясняет этот метод.
#!/bin/bash
USG_ERR=7
ret_val=
max_two ( ) {
if [ "$1" -eq "$2" ] ; then
echo 'Equal'
exit 0
elif [ "$1" -gt "$2" ] ; then
ret_val=$1
else
ret_val=$2
fi
}
err_str ( ) {
echo "Usage: $0 <number1> <number2>"
exit $USG_ERR
}
NUM_1=$1
NUM_2=$2
if [ $# -ne 2 ] ; then
err_str
elif [ `expr $NUM_1 : '[0-9]*'` -eq ${#NUM_1} ] ; then
if [ `expr $NUM_2 : '[0-9]*'` -eq ${#NUM_2} ] ; then
max_two $NUM_1 $NUM_2
echo $ret_val
else
err_str
fi
else
err_str
fi
exit 0
Теперь попробуйте решить некоторые интересные задачи, которые были объяснены в предыдущей серии сценариев оболочки, используя следующие функции.
- Основные советы по языку сценариев оболочки Linux. Часть I.
- 5 сценариев оболочки для новичков в Linux для изучения программирования оболочки – часть II
- Путешествуя по миру сценариев BASH для Linux – часть III
- Математический аспект программирования оболочки Linux. Часть IV.
- Вычисление математических выражений на языке сценариев Shell – Часть V
В следующей части я вернусь с более подробной информацией о функциональных возможностях, таких как использование локальных переменных, рекурсия и т. д. Будьте в курсе комментариев.