В
командной оболочке можно определять функции, и, если вы пишете сценарии
любого размера, функции можно применять для структурирования кода.
********** Как
альтернативу можно использовать разбиение большого сценария на много
маленьких, каждый из которых выполняет небольшую задачу. У этого подхода
есть несколько недостатков: выполнение вложенного в сценарий другого
сценария будет гораздо медленнее, чем выполнение функции. Значительно
труднее возвращать результаты, и может появиться большое количество
маленьких сценариев. Следует рассмотреть наименьшую практически
самостоятельную часть вашего сценария и использовать ее как эталон для
того, чтобы определить, когда возникает необходимость разбиения большого
сценария на коллекцию меньших по размеру сценариев **********
Для
определения функции в командной оболочке просто введите ее имя и следом
за ним пустые круглые скобки, а операторы тела функции заключите в
фигурные скобки.
Имя_функции() { операторы }
Давайте начнем с действительно простой функции
cat >> f #!/bin/bash
foo() { echo "Function foo is executing" }
echo "script starting" foo echo "script ended" exit 0
Выполняющийся сценарий выведет на экран слудующий текст:
chmod +x f ./f script starting Function foo is executing script ended
Данный
сценарий начинает выполняться с первой строки. Таким образом, ничего
необычного нет, но, когда он находит конструкцию foo() {, он знает, что
здесь дается определение функции, названной foo. Он запоминает ссылку на
функцию и foo продолжает выполнение после обнаружения скобки}. Когда
выполняется строка с единственным именем foo, командная оболочка знает,
что нужно выполнить предварительно определенную функцию. Когда функция
завершится, выполнение сценария продолжится в строке, следующей за
вызовом функции foo.
Вы
должны всегда определить функцию прежде, чем сможете ее запустить,
немного похоже на стиль, принятый в языке программирования Pascal, когда
вызову функции предшествует ее определение, за исключением того, что
командной оболочке нет опережающего объявления(forward) функции. Это
ограничение не создает проблем, потому что все сценарии выполняются с
первой строки, поэтому если просто поместить все определения функции
перед первым вызовом любой функции, все функции окажутся определенными
до того, как будут вызваны.
Когда
функция вызывается, позиционные параметры сценаря $*, $@, $#, $1, $2 и
т.д. заменяются параметрами функции. Именно так вы считываете параметры,
передаваемые функции. Когда функция завершится, они восстановит свои
прежние значения.
**************** Некоторые
более ранние командные оболочки не могут восстанавливать значение
позиционных параметров после выполнения функции. Не стоит полагаться на
описанное в предыдущем абзаце поведение, если вы хотите, что бы ваши
сценарии были переносимыми. **********
Вы
можете заставить функцию возвращать числовые значения с помощью команды
return. Обычно способ возврата функцией строковых значений -сохранение
строки в переменной, которую можно использовать после завершения
функции. Другой способ - вывести строку с помощью команды echo и
перехватить результат, как показано далее
foo () {echo JAY;}
result="$(foo)"
Вы
можете объявлять локальные переменные в функциях командной оболочки с
помощью ключевого слова local. В этом случае переменная действительна
только в пределах функции. В других случаях функция может обращаться к
переменным командной оболочки, у которых глобальная область действия.
Если у локальной переменной то же имя, что и у глобальной, в пределах
функции локальная переменная перекрывает глобальную. Для того чтобы
убедится в этом на практике, можно изменить предыдущий сценарий
следующим образом.
#!/bin/sh
samptle_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. Вы можете вызвать этот сценарий с параметром, задающий имя,
которое вы хотите использовать в вопросе.
#!/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" ecas done }
echo "Original parameters are $*" if yes_or_no "$1" then echo "Hi $1,nice name" else echo "never mind" fi exit 0
____________________
./my_name Rick Neil Original parameters are Rick Neil Is your name Rick ? Enter yes or no: yes Hi Rick, nice name
Когда
сценарий начинает выполнятся, функция определена, но еще не
выполняется. В операторе if сценарий вызывает функцию yes_or_no,
передавая ей оставшуюся часть строки как параметр после замены $1 первым
параметром исходного сценария строкой Rick. Функция использует эти
параметры, в данный момент хранящиеся в позиционных параметрах $1,$2 и
т.д. и возвращенного функцией значения конструкция if выполняет один из
операторов
Как
видите, у командной оболочки есть большой набор управляющих структур и
условных операторов. Вам необходимо познакомится с некоторыми командами,
встроенными в оболочку.
|