Для определения функции в командной оболочке просто введите ее имя и следом за ним пустые круглые скобки, а операторы тела функции заключите в фигурные скобки.
Имя_функции() {
операторы
}
Выполните упражнения 2.11 и 2.12.
Давайте начнем с действительно простой функции.
#!/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
, задающей возвращаемое значение, функция возвращает статус завершения последней выполненной команды,
В следующем сценарии, 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
Типичный вывод этого сценария может выглядеть следующим образом: