Книга: UNIX — универсальная среда программирования
3.8 Циклы в shell-программах
Разделы на этой странице:
3.8 Циклы в shell-программах
Язык shell
— действительно язык программирования: в нем есть переменные, циклы, ветвления и т.п. Здесь мы обсудим основные циклы, а структуры управления рассмотрим более подробно в гл. 5.
Типичным считается цикл по последовательности имен файлов, и оператор for
языка shell
является единственной структурой управления, которую обычно задают с терминала, а не помещают в файл для последующего выполнения. Синтаксис оператора for
таков:
for перем in список_слов
do
команды
done
Например, для получения эха имен файлов по одному на строке достаточно задать:
$ for i in *
> do
> echo $i
> done
Вместо i
можно применять любую переменную языка shell
, но это обозначение традиционно. Заметьте, что значение переменной получается с помощью $i
, однако в заголовке цикла переменную указывают как i
. Мы задействовали *
для выбора всех файлов текущего каталога, но можно использовать и любой другой список аргументов. Обычно нужно сделать что-нибудь более интересное, чем печать имен файлов. Нам часто приходилось сравнивать набор файлов с их предыдущими версиями, например старую версию гл. 2 (хранимую в каталоге old
) с текущей:
$ ls ch2. * | 5
Добавим пустую строку для красоты
ch2.1 ch2.2 ch2.3 ch2.4 ch2.5
ch2.6 ch2.7
$ for i in ch2.*
> do
> echo $i
> diff -b old/$i $i
> echo
> done | pr -h "diff `pwd`/old `pwd` | lpr &
Номер процесса
3712
$
Выходной поток направлен по конвейеру через команды pr
и lpr
просто для того, чтобы показать, что это возможно: стандартный выходной поток программ, находящихся внутри цикла for
, попадает в стандартный выходной поток самой команды for
. С помощью флага -h
в команде pr мы поместили в выходной поток заголовок с "архитектурными излишествами", используя два вложенных обращения к pwd
. Вся последовательность команд запущена асинхронно (&
), так что не нужно ждать ее окончания; &
применяется ко всякому циклу и конвейеру.
Мы предпочитаем указанный формат для цикла for
, но вы можете сократить его. Единственное ограничение заключается в том, что do
и done
распознаются как ключевые слова, только если они появляются сразу после перевода строки или точки с запятой. В зависимости от размера цикла for
иногда лучше помещать все на одной строке:
for i in список; do команды; done
Следует использовать цикл for
для обработки составных команд или в тех случаях, когда не подходит встроенная обработка отдельных команд. Но не применяйте его там, где в отдельной команде есть цикл по именам файлов:
# Плохая идея:
for i in $*
do
chmod +x $i
done
Предпочтительнее сделать так:
chmod +x $*
поскольку в цикле for
отдельная команда chmod
выполняется для каждого файла, что требует больших вычислительных ресурсов. (Убедитесь в том, что вы понимаете разницу между командами
for i in *
в которой цикл выполняется по всем именам файлов текущего каталога, и
for i in $*
в которой цикл выполняется по всем аргументам командного файла.)
Список аргументов для цикла for
часто получают путем выбора имен файлов по шаблону, но можно получать и любым другим способом, в частности:
for i in `cat ...`
или просто вводом аргументов. Например, ранее в этой главе мы создали ряд программ для печати в несколько столбцов под именами 2
, 3
и т.д. Они являются связями с одним файлом, которые можно установить следующим образом (при условии, что программа 2
написана):
$ for i in 3 4 5 6; do ln 2 $i; done
$
Цикл for
имеет и более интересное назначение. Выберем с помощью команды pick
те файлы, которые будут сравниваться с файлами из каталога старых версий:
$ for i in `pick ch2.*`
> do
> echo $i:
> diff old/$i $i
> done | pr | lpr
ch2.1? y
ch2.2
ch2.3
ch2.4? y
ch2.5? y
ch2.6?
ch2.7?
$
Очевидно, данный цикл следует поместить в командный файл, чтобы уменьшить ввод в следующий раз (ведь если вы что-то сделали дважды, вероятно, вы сделаете это и в третий раз).
Упражнение 3.15
Если цикл с командой diff
хранится в командном файле, поместите ли вы туда команду pick? Объясните, почему.
Упражнение 3.16
Что произойдет, если последняя строка приведенного цикла будет иметь вид:
> done | pr | lpr &
т.е. кончаться амперсандом? Попробуйте сделать прогноз, а затем проверьте его.
- 3.1 Структура командной строки
- 3.2 Метасимволы
- 3.3 Создание новых команд
- 3.4 Аргументы и параметры команд
- 3.5 Результат выполнения программы в качестве аргумента
- 3.6 Переменные языка shell
- 3.7 Еще раз о переключении ввода-вывода
- 3.8 Циклы в shell-программах
- 3.9 Программа bundle: соберем все воедино
- 3.10 Для чего нужно программировать на языке shell!
- Глава 3 Возможности интерпретатора shell
- Жизненные циклы продуктов
- 1.2.6. Циклы и ветвление
- Что делать, если вместо русских букв в программах – непонятные символы?
- Лекция 3. Формы и циклы
- Основные сведения о базах данных и программах для их обработки
- Managing Files with the Shell
- Basic Shell Control
- The Shell Command Line
- Shell Pattern-Matching Support
- Access to the Shell
- Why Use the Shell?