Перейти к основному содержанию
Рецепты Linux

Main navigation

  • Основы
  • Система
  • Команды
  • Программы
  • Дистро
  • Интерфейсы
  • Устройства
  • Доки
User account menu
  • Войти

Строка навигации

  1. Главная
  2. ABS Guide
  3. Часть 4. Материал повышенной сложности
  4. Глава 22. Функции

22.2. Локальные переменные

Что такое "локальная" переменная?

локальные переменные

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

Пример 22-11. Область видимости локальных переменных

#!/bin/bash

func ()
{
 local loc_var=23 # Объявление локальной переменной.
 echo
 echo "\"loc_var\" в функции = $loc_var"
 global_var=999 # Эта переменная не была объявлена локальной.
 echo "\"global_var\" в функции = $global_var"
}

func

# Проверим, "видна" ли локальная переменная за пределами функции.

echo
echo "\"loc_var\" за пределами функции = $loc_var"
 # "loc_var" за пределами функции =
 # Итак, $loc_var не видна в глобальном контексте.
echo "\"global_var\" за пределами функции = $global_var"
 # "global_var" за пределами функции = 999
 # $global_var имеет глобальную область видимости.
echo 

exit 0
Caution

Переменные, объявляемые в теле функции, считаются необъявленными до тех пор, пока функция не будет вызвана. Это касается всех переменных.

#!/bin/bash

func ()
{
global_var=37 # Эта переменная будет считаться необъявленной
 #+ до тех пор, пока функция не будет вызвана.
} # КОНЕЦ ФУНКЦИИ

echo "global_var = $global_var" # global_var =
 # Функция "func" еще не была вызвана,
 #+ поэтому $global_var пока еще не "видна" здесь.

func
echo "global_var = $global_var" # global_var = 37
 # Переменная была инициализирована в функции.

22.2.1. Локальные переменные делают возможной рекурсию.

Хотя локальные переменные и допускают рекурсию, [52] но она сопряжена с большими накладными расходами и не рекомендуется для использования в сценариях. [53]

Пример 22-12. Использование локальных переменных при рекурсии

#!/bin/bash

# факториал
# ---------


# Действительно ли bash допускает рекурсию?
# Да! Но...
# Нужно быть действительно дубинноголовым, чтобы использовать ее в сценариях
# на языке командной оболочки.


MAX_ARG=5
E_WRONG_ARGS=65
E_RANGE_ERR=66


if [ -z "$1" ]
then
 echo "Порядок использования: `basename $0` число"
 exit $E_WRONG_ARGS
fi

if [ "$1" -gt $MAX_ARG ]
then
 echo "Выход за верхний предел (максимально возможное число -- 5)."
 # Вернитесь к реальности.
 # Если вам захочется поднять верхнюю границу,
 # то перепишите эту программу на настоящем языке программирования.
 exit $E_RANGE_ERR
fi

fact ()
{
 local number=$1
 # Переменная "number" должна быть объявлена как локальная,
 # иначе результат будет неверный.
 if [ "$number" -eq 0 ]
 then
 factorial=1 # Факториал числа 0 = 1.
 else
 let "decrnum = number - 1"
 fact $decrnum # Рекурсивный вызов функции.
 let "factorial = $number * $?"
 fi
	 
 return $factorial
}
	 
fact $1
echo "Факториал числа $1 = $?."
	 
exit 0

Еще один пример использования рекурсии вы найдете в Пример A-18. Не забывайте, что рекурсия весьма ресурсоемкое удовольствие, к тому же она выполняется слишком медленно, поэтому не следует использовать ее в сценариях.

Notes

[52]

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

[53]

Слишком глубокая рекурсия может вызвать крах сценария.


#!/bin/bash
# Осторожно: Этот сценарий может подвесить систему!
# Если вам повезет, то вы получите segfault прежде, чем будет исчерпана вся доступная память.


recursive_function ()
{
(( $1 < $2 )) && recursive_function $(( $1 + 1 )) $2;
# Увеличивать 1-й параметр до тех пор,
#+ пока он не станет равным, или не превысит, второму параметру.
}

recursive_function 1 50000 # Глубина рекурсии = 50,000!
# Наиболее вероятное развитие событий -- segfaults (в зависимости от объема стека).

# Рекурсия такой глубины может "обрушить" даже программу, написанную на C,
#+ по исчерпании памяти, выделенной под сегмент стека.

# Спасибо S.C.

echo "Эта строка не должна быть выведена на экран."
exit 0 # Этот сценарий завершается аварийно (в лучшем случае).

# Thanks, Stephane Chazelas.

Перекрёстные ссылки книги для 22.2. Локальные переменные

  • 22.1. Сложные функции и сложности с функциями
  • Вверх
  • 22.3. Рекурсия без локальных переменных

Book navigation

  • Содержание
  • Часть 1. Введение
  • Часть 2. Основы
  • Часть 3. Углубленный материал
  • Часть 4. Материал повышенной сложности
    • Глава 18. Регулярные выражения
    • Глава 19. Подоболочки, или Subshells
    • Глава 20. Ограниченный режим командной оболочки
    • Глава 21. Подстановка процессов
    • Глава 22. Функции
      • 22.1. Сложные функции и сложности с функциями
      • 22.2. Локальные переменные
      • 22.3. Рекурсия без локальных переменных
    • Глава 23. Псевдонимы
    • Глава 24. Списки команд
    • Глава 25. Массивы
    • Глава 26. Файлы
    • Глава 27. /dev и /proc
    • Глава 28. /dev/zero и /dev/null
    • Глава 29. Отладка сценариев
    • Глава 30. Необязательные параметры (ключи)
    • Глава 31. Широко распространенные ошибки
    • Глава 32. Стиль программирования
    • Глава 33. Разное
    • Глава 34. Bash, версия 2
  • Глава 35. Замечания и дополнения
  • Библиография
  • Приложение A. Дополнительные примеры сценариев
  • Приложение B. Справочная информация
  • Приложение C. Маленький учебник по Sed и Awk
  • Приложение D. Коды завершения, имеющие предопределенный смысл
  • Приложение E. Подробное введение в операции ввода-вывода и перенаправление ввода-вывода
  • Приложение F. Системные каталоги
  • Приложение G. Локализация
  • Приложение H. История команд
  • Приложение I. Пример файла .bashrc
  • Приложение J. Преобразование пакетных (*.bat) файлов DOS в сценарии командной оболочки
  • Приложение K. Упражнения
  • Приложение L. Хронология
  • Приложение M. Авторские права

Последние материалы

  • Приложение scanimage
    7 hours 55 minutes ago
  • Утилита sensors
    4 days ago
  • Сканер Rkhunter
    1 week 4 days ago
  • Программа resize2fs
    2 weeks 3 days ago
  • Аудиопроигрыватель QMMP
    3 weeks 1 day ago
RSS feed

Secondary menu

  • О проекте

© 2008–2025 Олег Меньшенин mensh@yandex.ru