При обычном выполнении команд одна команда выполняется за другой. Выполняется первая команда, затем следующая команда, затем команда после, и так далее. Представьте себе сценарий с сотней команд, каждая из которых находится в строке. Возможны две, три или более последовательных команд, которые повторяются в разных частях сценария. Другими словами, один и тот же сегмент команд появляется после разных уникальных команд, поскольку сценарий просматривается сверху вниз.
Было бы лучше иметь сегмент команд как одну группу, когда это должно произойти впервые. Затем просто вызывайте группу каждый раз, когда она нужна в сценарии. Для этого группе нужно дать имя.
Функция – это именованная группа команд, которая вызывается всякий раз, когда это необходимо, в сценарии. Группа команд не выполняется, если функция определена в верхней части скрипта. Группа выполняется только при вызове функции.
Содержание статьи
– Примеры функций
– Позиционные параметры
– Функции возврата
– Глобальный и локальный охват
– Рекурсивная функция
– Заключение
Примеры функций
Функция без параметров
Рассмотрим следующую группу команд:
mkdir myDir cd myDir touch myfile.txt
Первая команда создает каталог myDir. Вторая команда делает myDir текущим каталогом. Третья команда создает файл myFile.txt в текущем каталоге. Если бы этот сегмент кода должен был быть повторен три раза в длинном скрипте, то было бы лучше поместить его в функцию, дав ей имя. Помещение его в функцию – это определение функции. Функция должна быть определена в верхней части скрипта, а затем вызываться три раза в разных точках скрипта. При запуске скрипта группа команд в определении функции не выполняется. Они выполняются, когда функция вызывается в скрипте. То есть, когда вы запускаете сценарий, определение функции устанавливается, но не выполняется. Функция выполняется при ее вызове в скрипте.
Эта функция будет определяться и вызываться трижды следующим образом:
PS1='\w\$ ' function aFn { mkdir myDir cd myDir touch myfile.txt } aFn aFn aFn
Первая строка в скрипте не является частью определения функции или какого-либо вызова функции. Это заставляет команду cd работать более эффективно. Определение функции начинается с зарезервированного слова «function». Далее следует пробел, а затем имя функции. Название функции выбирает программист. После имени функции должен стоять пробел перед знаком «{». Первой команде в теле функции должен предшествовать пробел после символа «{». Последняя команда в теле должна быть отделена от разделителя «}» новой строкой или «;» или же “&”.
В сценарии функция была вызвана три раза после определения функции с именем функции aFn.
Результатом сценария является создание каталога с именем myDir. Внутри myDir создается файл myfile.txt. Создается еще один myDir и вложенный myFile.txt, вложенный в первый myDir. Тем не менее, создается еще один myDir и вложенный myFile.txt, вложенный во второй myDir.
Функция с параметрами
Представьте, что на столе лежат 3 учебника и 2 тетради. Общее количество книг – 5. Следующий скрипт показывает, как это добавление и отображение результата может быть выполнено:
add () { sum=$((${1} + ${2})) echo $sum ${3} } add 3 2 "книг"
Определение функции начинается с имени функции «add», данного программистом. За ним следуют круглые скобки с пробелом перед ним или без него. За ним следует “{“, которому предшествует пробел. Команды следуют; а затем новую строку или «;» или «&»; и наконец “}”.
Если функция не принимает аргументы (параметры), ее определение должно начинаться с зарезервированного слова «function», затем имени функции и без скобок. Когда он принимает аргументы, его определение должно начинаться с имени функции и сопровождаться круглыми скобками.
Последняя команда в скрипте вызывает функцию. Его первый аргумент – 3, его второй аргумент – 2, а его третий аргумент – «книги». Если аргумент является числом, его следует вводить без кавычек. Если это строка из одного или нескольких слов, ее следует вводить в одинарные или двойные кавычки.
В определении функции первый аргумент получается с помощью $ {1}, второй аргумент получается с помощью $ {2}, а третий аргумент получается с помощью $ {3}. Если бы был четвертый аргумент, он был бы получен с помощью $ {4}; и так далее.
Bash по умолчанию добавляет только целые числа. Для сложения двух чисел с плавающей запятой или целого числа и числа с плавающей запятой требуется специальная конструкция. См. Пример ниже:
Позиционные параметры
$ {1}, $ {2}, $ {3} и т. д., Использованные выше, являются позиционными параметрами. Обычный счет в программировании начинается с 0. Итак, в чем польза от $ {0}? $ {0} содержит имя, которому предшествует путь к сценарию Bash. Следующий код иллюстрирует это:
add() { sum=`echo ${1} + ${2} | bc` echo Сумма is $sum для сценария ${0} . } add 3.5 2.4
Результат:
Где «./temp.ru» – это путь и имя сценария автора. Обратите внимание на строку и обратные кавычки для добавления чисел с плавающей запятой.
Возврат функции
Обратите внимание на то, что в приведенной выше функции были добавлены два целых числа. Вместо повторения результата результат мог быть возвращен с зарезервированным словом «return», как показано в следующем сценарии:
add () { sum=$((${1} + ${2})) return $sum } add 3 2 echo $? книг
Результат:
5 книг
В определении функции команда return возвращает сумму. Это возвращаемое значение хранится в специальной переменной «$?».
Глобальный и локальный охват
Рассмотрим следующий сценарий:
var=5 function fn { var=6 echo $var } echo $var
Результатом будет 5. Это потому, что функция не была вызвана. Переменная вне функции находится в глобальной области видимости, а переменная внутри функции находится в локальной области видимости. Обе переменные имеют одинаковое имя и должны означать одно и то же.
Когда функция вызывается, ее тело видит глобальную переменную области видимости. Следующий сценарий иллюстрирует это:
var=5 function fn { var=6 echo $var } fn echo $var
Результат:
6 6
Функция вызывается до того, как глобальная переменная будет отражена в последних двух командах сценария. Когда функция была вызвана, она увидела глобальную переменную и изменила ее значение с 5 на 6.
Локальная переменная внутри тела функции может быть независимой от глобальной переменной вне определения функции. Это делается путем объявления переменной внутри функции как локальной с зарезервированным словом «local». Следующий сценарий иллюстрирует это:
var=5 function fn { local var=6 echo $var } fn echo $var
Результат:
6 5
Из-за зарезервированного слова «local» локальная переменная с тем же именем видна только в теле функции. Напротив, глобальная переменная с тем же именем видна только вне тела функции, а не в теле функции.
Рекурсивная функция
Рекурсивная функция – это функция, которая вызывает себя многократно, пока не будет выполнено определенное условие. Первый сценарий выше, в котором функция вызывалась 3 раза, можно превратить в рекурсивную функцию. Условие – 3 звонка. Это можно сделать с помощью переменной счетчика. Следующий сценарий иллюстрирует это:
PS1='\w\$ ' counter=0 function aFn { mkdir myDir cd myDir touch myfile.txt ((counter=$counter + 1)) if [ $counter -le 2 ]; then aFn fi } aFn
Обратите внимание, как условие, которое должно быть выполнено, было закодировано в конструкции if. В нулевом проходе функции после того, как она была вызвана, счетчик равен 1. На первом проходе функции счетчик равен 2. Во втором проходе функции счетчик равен 3. Это рекурсивная функция.
Заключение
Функция – это группа команд, которая может быть вызвана хотя бы один раз в скрипте. Функция должна иметь имя, данное ей программистом. Позиционные параметры функции: ${1}, ${2}, ${3} и т. д. В соответствии с порядком аргументов. Число в качестве аргумента пишется без кавычек. Строковый аргумент из одного или нескольких слов записывается в кавычки. Функция может возвращать значение. Возвращаемое значение хранится в специальной переменной «$?». Переменная внутри тела функции может переопределить переменную вне тела функции с помощью зарезервированного слова «local». Функция в Bash может быть рекурсивной. То есть после первого звонка он может вызывать себя снова и снова. Чтобы прекратить повторение, должно быть выполнено условие.