Глава 22. Функции


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

function function_name {
command...
}

или

function_name () {
command...
}



Вторая форма записи ближе к сердцу C-программистам (она же более переносимая).

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

function_name ()
{
command...
}



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

Пример 22-1. Простые функции

  1. #!/bin/bash
  2. JUST_A_SECOND=1
  3. funky ()
  4. { # Это пример простейшей функции, которая выводит сообщение.
  5.   echo "Это функция funky."
  6. } # Объявление функции должно предшествовать ее вызову.
  7. fun ()
  8. { # Более сложная функция.
  9.   i=0
  10.   REPEATS=30
  11.   echo
  12.   echo "Теперь запускается функция fun."
  13.   echo
  14.   sleep $JUST_A_SECOND    # Эй! Погодите секундочку!
  15.   while [ $i -lt $REPEATS ]
  16.   do
  17.     echo "------------------РАБОТА------------------->"
  18.     echo "<---------------С ФУНКЦИЯМИ----------------"
  19.     echo "<------------ОЧЕНЬ УВЛЕКАТЕЛЬНА------------>"
  20.     echo
  21.     let "i+=1"
  22.   done
  23. }
  24.   # А теперь собственно вызов функций.
  25. funky
  26. fun
  27. exit 0

Функция должна быть объявлена раньше, чем ее можно будет использовать. К сожалению, в Bash нет возможности "опережающего объявления" функции, как например в C.

  1. f1
  2. # Эта строка вызовет сообщение об ошибке, поскольку функция "f1" еще не определена.
  3. declare -f f1      # Это не поможет.
  4. f1                 # По прежнему — сообщение об ошибке.
  5. # Однако...
  6. f1 ()
  7. {
  8.   echo "Вызов функции \"f2\" из функции \"f1\"."
  9.   f2
  10. }
  11. f2 ()
  12. {
  13.   echo "Функция \"f2\"."
  14. }
  15. f1  #  Функция "f2", фактически, не вызывается выше этой строки,
  16.     #+ хотя ссылка на нее встречается выше, до ее объявления.
  17.     #  Это допускается.
  18.     # Спасибо S.C.


Допускается даже создание вложенных функций, хотя пользы от этого немного.

  1. f1 ()
  2. {
  3.   f2 () # вложенная
  4.   {
  5.     echo "Функция \"f2\", вложенная в \"f1\"."
  6.   }
  7. }
  8. f2  #  Вызывает сообщение об ошибке.
  9.     #  Даже "declare -f f2" не поможет.
  10. echo
  11. f1  #  Ничего не происходит, простой вызов "f1", не означает автоматический вызов "f2".
  12. f2  #  Теперь все нормально, вызов "f2" не приводит к появлению ошибки,
  13.     #+ поскольку функция "f2" была определена в процессе вызова "f1".
  14.     # Спасибо S.C.


Объявление функции может размещаться в самых неожиданных местах.

  1. ls -l | foo() { echo "foo"; }  # Допустимо, но бесполезно.
  2. if [ "$USER" = bozo ]
  3. then
  4.   bozo_greet ()   # Объявление функции размещено в условном операторе.
  5.   {
  6.     echo "Привет, Bozo!"
  7.   }
  8. fi
  9. bozo_greet        # Работает только у пользователя bozo, другие получат сообщение об ошибке.
  10. # Нечто подобное можно использовать с определеной пользой для себя.
  11. NO_EXIT=1   # Will enable function definition below.
  12. [[ $NO_EXIT -eq 1 ]] && exit() { true; }     # Определение функции в последовательности "И-список".
  13. # Если $NO_EXIT равна 1, то объявляется "exit ()".
  14. # Тем самым, функция "exit" подменяет встроенную команду "exit".
  15. exit  # Вызывается функция "exit ()", а не встроенная команда "exit".
  16. # Спасибо S.C.