BashЯзык командного интерпретатора bash. Part 7. «Функции»

Вот и наступил черёд седьмого топика цикла о языке командного интерпретатора bash. В некотором роде число «7» является везучим, как говорят в народе. Надеюсь, и меня не обойдёт данная примета.
Сегодня будут разобраны такие конструкции языка bash, как функции. Надеюсь, тебе не нужно рассказывать о том, что такое функция и для чего она применяется, ведь её смысл эквивалентен понятию функции из любого другого языка программирования. Объём информации сегодня не большой, поэтому пост имеет довольно скромные размеры. Итак, приступим к непосредственному разбору функций в bash.
Общий синтаксис оператора определения функции:
[function] имя_функции () {
список_комманд
}

Кроме K&R-стиля также применим BSD-стиль:
[function] имя_функции ()
{
список_комманд
}

Вызвать функцию можно в любом месте сценария, но перед этим она должна быть объявлена. Вызов осуществляется указанием имени функции в тексте скрипта.
#определение функции
func1 () {
  echo "Hello."
} 
#вызов функции
funс1

Функции принимают входные аргументы и возвращают код завершения. Доступ к входным аргументам осуществляется через позиционные параметры. Позиционный параметр 0 содержит имя функции. Внутри функции доступны локальные переменные сценария. Приведу пример:
param1=Hello
func2 () {
param2=${1-$param1}
echo "param2 = $param2"
}

Теперь пример с аргументами:
func3 () {
if [ "$1" ]
then
echo "Аргумент #1: \"$1\".-"
fi
if [ "$2" ]
then
echo "Аргумент #2: \"$2\".-"
fi
}
func3 #вызов функции без аргументов
func3 arg1 #вызов функции с одним аргументом
func3 arg1 arg2 #вызов функции с двумя аргументами

Если при выполнении функции произошла ошибка, происходит завершение выполнения функции с ненулевым кодом возврата. Код завершения можно задавать явно с помощью команды return. Код завершения в сценарии может быть получен через переменную $? и доступен до выполнения следующей команды.
Возможности bash позволяют переопределить stdin для функции, чтобы получать входные данные из файла. Для этого служит конструкция:
имя_функции ()
{
список_команд
} < файл
Также возмож
ен следующий вариант:
имя_функции ()
{
{
список_команд
} < файл
}


Следующий пост будет повествовать об обработке сигналов и протоколировании в bash. Жду ваших комментариев :).

Комментарии (4)

  • avatar
  • Dez
  • 15 июля 2009, 22:02
  • #
  • 2
Коротко и ясно.
Спасибо большое. Ждем продолжения
Нажеюсь, оно будет завтра :).
Немного моего соуса в блюдо Istergul'а:

Пример1
Часто вижу линуксойдов, которые постоянно (когда хотят обратится к какому-то файлу) переходят в директорию(cd /home), затем смотрят её содержимое (ls), затем переходят дальше (cd /home/aonick), опять (ls) и тд… до достижения файла — для них:
lcd(){
  echo "Директория: $1"
  cd $1 && ls
}
После этого переходить в нужную директорию можно так:
lcd /home
это команда и в директорию перейдет и сразу содержимое покажет.

Пример 2
Так как функция выполняется в той же сессии (в отличии от скрипта) — удобно например для команд настраивать автозаполнение по Тab-клавиши, напимер для команды rpm чтобы дописывал из списка установленных пакетов:
_rpm-refresh(){ complete -W "$(rpm -qa) -ivh -ql -qi" rpm; }

После этого — каждый раз когда запускаю функцию:
_rpm-refresh
обновляется список аргументов которые предлагаются по нажатию Tab.
И пользуясь командой rpm уже так, например:
rpm -ql apach<i><Нажимаю  дважды Tab></i>
и вижу список установленных пакетов начинающихся с «apach»

Дополнение:
Функция задается только в текущей сессии и после закрытия терминал про неё система забудет. Чтобы навеки-вечные задать своему пользователю функцию — её прописывают в файл ".bashrc" в домашней директории пользователя.

Спасибо! Оптимизировал парочку скриптов. Быть может теперь мотивируюсь осилить ABS :)
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.