Применяйте конструкцию for
для обработки в цикле ряда значений, которые могут представлять собой любое множество строк. Строки могут быть просто перечислены в программе или, что бывает чаще, представлять собой результат выполненной командной оболочкой подстановки имен файлов.
Синтаксис этого оператора прост:
for
переменная
in
значения
do
операторы
done
Выполните упражнения 2.4 и 2.5.
for
к фиксированным строкамВ командной оболочке значения обычно представлены в виде строк, поэтому можно написать следующий сценарий:
#!/bin/sh
for foo in bar fud 43
do
echo $foo
done
exit 0
В результате будет получен следующий вывод:
bar
fud
43
Что произойдет, если вы измените первую строку с for foo in bar fud 43
на for foo in "bar fud 43"
? Напоминаем, что вставка кавычек заставляет командную оболочку считать все, что находится между ними, единой строкой. Это один из способов сохранения пробелов в переменной.
Как это работает
В данном примере создается переменная foo
и ей в каждом проходе цикла for
присваиваются разные значения. Поскольку оболочка считает по умолчанию все переменные строковыми, применять строку 43 так же допустимо, как и строку fud
.
for
с метасимволамиКак упоминалось ранее, цикл for
обычно используется в командной оболочке вместе с метасимволами или знаками подстановки для имен файлов. Это означает применение метасимвола для строковых значений и предоставление оболочке возможности подставлять все значения на этапе выполнения.
Вы уже видели этот прием в первом примере first. В сценарии применялись средства подстановки командной оболочки — символ *
для подстановки имен всех файлов из текущего каталога. Каждое из этих имен по очереди используется в качестве значения переменной $file
внутри цикла for
.
Давайте бегло просмотрим еще один пример подстановки с помощью метасимвола. Допустим, что вы хотите вывести на экран все имена файлов сценариев в текущем каталоге, начинающиеся с буквы "f", и вы знаете, что имена всех ваших сценариев заканчиваются символами .sh. Это можно сделать следующим образом:
#!/bin/sh
for file in $(ls f*.sh); do
lpr $file
done
exit 0
Как это работает
В этом примере показано применение синтаксической конструкции $(команда)
, которая будет подробно обсуждаться далее (в разделе, посвященном выполнению команд). Обычно список параметров для цикла for
задается выводом команды, включенной в конструкцию $()
.
Командная оболочка раскрывает f*.sh
, подставляя имена всех файлов, соответствующих данному шаблону.
Помните о том, что все подстановки переменных в сценариях командной оболочки делаются во время выполнения сценария, а не в процессе их написания, поэтому все синтаксические ошибки в объявлениях переменных обнаруживаются только на этапе выполнения, как было показано ранее, когда мы заключали в кавычки пустые переменные.
Поскольку по умолчанию командная оболочка считает все значения строками, оператор for
хорош для циклической обработки наборов строк, но не слишком удобен, если вы не знаете заранее, сколько раз придется его выполнить.
Если нужно повторить выполнение последовательности команд, но заранее не известно, сколько раз следует их выполнить, вы, как правило, будете применять цикл while
со следующей синтаксической записью:
while условие
do
операторы
done
Далее приведен пример довольно слабой программы проверки паролей.
#!/bin/sh
echo "Enter password"
read trythis
while [ "$trythis" != "secret" ]; do
echo "Sorry, try again"
read trythis
done
exit 0
Следующие строки могут служить примером вывода данного сценария:
Enter password
password
Sorry, try again
secret
$
Ясно, что это небезопасный способ выяснения пароля, но он вполне подходит для демонстрации применения цикла while
. Операторы, находящиеся между операторами do
и done
, выполняются бесконечное число раз до тех пор, пока условие остается истинным (true
). В данном случае вы проверяете, равно ли значение переменной trythis
строке secret
. Цикл будет выполняться, пока $trythis
не равно secret
. Затем выполнение сценария продолжится с оператора, следующего сразу за оператором done
.
У цикла until
следующая синтаксическая запись: