Выбрать главу

Для определения функции в командной оболочке просто введите ее имя и следом за ним пустые круглые скобки, а операторы тела функции заключите в фигурные скобки.

Имя_функции() {

операторы

}

Выполните упражнения 2.11 и 2.12.

Упражнение 2.11. Простая функция

Давайте начнем с действительно простой функции.

#!/bin/sh

foo() {

 echo "Function foo is executing"

}

echo "script starting"

foo

echo "script ended"

exit 0

Выполняющийся сценарий, выведет на экран следующий текст:

script starting

Function foo is executingscript ended

Как это работает

Данный сценарий начинает выполняться с первой строки. Таким образом, ничего необычного нет, но, когда он находит конструкцию foo() {, он знает, что здесь дается определение функции, названной foo. Он запоминает ссылку на функцию и foo продолжает выполнение после обнаружения скобки }. Когда выполняется строка с единственным именем foo, командная оболочка знает, что нужно выполнить предварительно определенную функцию. Когда функция завершится, выполнение сценария продолжится в строке, следующей за вызовом функции foo.

Вы должны всегда определить функцию прежде, чем сможете ее запустить, немного похоже на стиль, принятый в языке программирования Pascal, когда вызову функции предшествует ее определение, за исключением того, что в командной оболочке нет опережающего объявления (forward) функции. Это ограничение не создает проблем, потому что все сценарии выполняются с первой строки, поэтому если просто поместить все определения функций перед первым вызовом любой функции, все функции окажутся определенными до того, как будут вызваны.

Когда функция вызывается, позиционные параметры сценария $*, $@, $#, $1, $2 и т.д. заменяются параметрами функции. Именно так вы считываете параметры, передаваемые функции. Когда функция завершится, они восстановят свои прежние значения.

Примечание

Некоторые более ранние командные оболочки не могут восстанавливать значения позиционных параметров после выполнения функций. Не стоит полагаться на описанное в предыдущем абзаце поведение, если вы хотите, чтобы ваши сценарии были переносимыми.

Вы можете заставить функцию возвращать числовые значения с помощью команды return. Обычный способ возврата функцией строковых значений — сохранение строки в переменной, которую можно использовать после завершения функции. Другой способ — вывести строку с помощью команды echo и перехватить результат, как показано далее.

foo() { echo JAY;}

...

result="$(foo)"

Вы можете объявлять локальные переменные в функциях командной оболочки с помощью ключевого слова local. В этом случае переменная действительна только в пределах функции. В других случаях функция может обращаться к переменным командной оболочки, у которых глобальная область действия. Если у локальной переменной то же имя, что и у глобальной, в пределах функции локальная переменная перекрывает глобальную. Для того чтобы убедиться в этом на практике, можно изменить предыдущий сценарий следующим образом.

#!/bin/sh

sample_text="global variable"

foo() {

 local sample_text="local variable"

 echo "Function foo is executing"

 echo $sample_text

}

echo "script starting"

echo $sample_text

foo

echo "script ended"

echo $sample_text

exit 0

При отсутствии команды return, задающей возвращаемое значение, функция возвращает статус завершения последней выполненной команды,

Упражнение 2.12. Возврат значения

В следующем сценарии, my_name, показано, как в функцию передаются параметры и как функции могут вернуть логический результат true или false. Вы можете вызвать этот сценарий с параметром, задающим имя, которое вы хотите использовать в вопросе.

1. После заголовка командной оболочки определите функцию yes_or_no.

#!/bin/sh

yes_or_no() {

 echo "Is your name $* ? "

 while true

 do

  echo -n "Enter yes or no: "

  read x

  case "$x" in

   y | yes ) return 0;;

   n | no )  return 1;;

   * )       echo "Answer yes or no"

  esac

 done

}

2. Далее начинается основная часть программы.

echo "Original parameters are $*"

if yes_or_no "$1"

then

 echo "Hi $1, nice name"

else

 echo "Never mind"

fi

exit 0

Типичный вывод этого сценария может выглядеть следующим образом: