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

Main navigation

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

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

  1. Главная
  2. ABS Guide
  3. Часть 4. Материал повышенной сложности
  4. Глава 33. Разное

33.4. Рекурсия

Может ли сценарий рекурсивно вызывать себя самого? Да, может!

Пример 33-6. Сценарий (бесполезный), который вызывает себя сам

#!/bin/bash
# recurse.sh

# Может ли сценарий вызвать себя сам?
# Да, но есть ли в этом смысл?

RANGE=10
MAXVAL=9

i=$RANDOM
let "i %= $RANGE" # Генерация псевдослучайного числа в диапазоне 0 .. $MAXVAL.

if [ "$i" -lt "$MAXVAL" ]
then
 echo "i = $i"
 ./$0 # Сценарий запускает новый экземпляр себя самого.
fi # если число $i больше или равно $MAXVAL.

# Если конструкцию "if/then" заменить на цикл "while", то это вызовет определенные проблемы.
# Объясните -- почему?.

exit 0

Пример 33-7. Сценарий (имеющий практическую ценность), который вызывает себя сам

#!/bin/bash
# pb.sh: телефонная книга

# Автор: Rick Boivie
# используется с его разрешения.
# Дополнен автором документа.

MINARGS=1 # Сценарию должен быть передан, по меньшей мере, один аргумент.
DATAFILE=./phonebook
PROGNAME=$0
E_NOARGS=70 # Ошибка, нет аргументов.

if [ $# -lt $MINARGS ]; then
 echo "Порядок использования: "$PROGNAME" data"
 exit $E_NOARGS
fi


if [ $# -eq $MINARGS ]; then
 grep $1 "$DATAFILE"
else
 ( shift; "$PROGNAME" $* ) | grep $1
 # Рекурсивный вызов.
fi

exit 0 # Сценарий завершает свою работу здесь.
 # Далее следует пример файла телефонной книги
 #+ в котором не используются символы комментария.

# ------------------------------------------------------------------------
# Пример файла телефонной книги

John Doe 1555 Main St., Baltimore, MD 21228 (410) 222-3333
Mary Moe 9899 Jones Blvd., Warren, NH 03787 (603) 898-3232
Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678
Zoe Zenobia 4481 N. Baker St., San Franciso, SF 94338 (415) 501-1631
# ------------------------------------------------------------------------

$bash pb.sh Roe
Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678

$bash pb.sh Roe Sam
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678

# Если сценарию передаются несколько аргументов,
#+ то выводятся только те строки, которые содержат их все.

Пример 33-8. Еще один сценарий, который вызывает себя сам

#!/bin/bash
# usrmnt.sh, автор Anthony Richardson
# Используется с его разрешения.

# Порядок использования: usrmnt.sh
# Описание: монтирует устройство, пользователь должен входить в состав группы
# MNTUSERS в файле /etc/sudoers.

# -----------------------------------------------------------------
# Этот сценарий рекурсивно вызывает себя самого,
#+ используя sudo. Пользователь, наделенный
#+ соответствующими правами может просто дать команду

# usermount /dev/fd0 /mnt/floppy

# вместо

# sudo usermount /dev/fd0 /mnt/floppy

# Подобную технику я использую во всех моих
#+ sudo-сценариях, поскольку она кажется мне достаточно удобной.
# -----------------------------------------------------------------

# Если переменная SUDO_COMMAND не определена, значит сценарий запущен не через
#+ sudo, поэтому повторно вызываем сценарий.
#+ Передвая user id и group id через переменные...

if [ -z "$SUDO_COMMAND" ]
then
 mntusr=$(id -u) grpusr=$(id -g) sudo $0 $*
 exit 0
fi
 
# В эту точку мы попадаем только если сценарий запущен через sudo
/bin/mount $* -o uid=$mntusr,gid=$grpusr
 
exit 0
 
# Дополнительные замечания от автора сценария:
# -------------------------------------------------
 
# 1) Linux допускает указание опции "users" в файле /etc/fstab,
# которая позволяет монтировать носители любому пользователю.
# Но на сервере я предпочитаю дать это право лишь отдельным
# пользователям. На мой взгляд sudo делает ситуацию более управляемой.
 
# 2) Я так же считаю, что утилита sudo более удобна, чем
# выполнение той же задачи посредством групп.
 
# 3) Эта методика выдает права root на доступ к команде
# mount, что требует особого внимания при выделении пользователей
# наделенных таким правом. Используя ту же самую технику,
# вы можете более точно разграничить права монтирования
# устройств, написав сценарии mntfloppy, mntcdrom и mntsamba.
Caution

Слишком глубокая рекурсия может привести к исчерпанию пространства, выделенного под стек, и "вываливанию" сценария по "segfault".

Перекрёстные ссылки книги для 33.4. Рекурсия

  • 33.3. Операции сравнения: Альтернативные решения
  • Вверх
  • 33.5. "Цветные" сценарии

Book navigation

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

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

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

Secondary menu

  • О проекте

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