Циклы и конструкции
Конструкция for...in предназначена для упрощения выполнения некоторых действий для группы значений или файлов, особенно при универсализации файловых имен, т.е. замене реальных символов в имени и расширении универсальными (например, "*" и "?") с целью формирования целых списков имен файлов. Шаблон *.sh в приведенном ниже цикле for позволяет обработать целый список совпадающих с ним (шаблоном) имен файлов из текущего каталога. Оператор for, проходя по этому списку, по очереди присваивает имя каждого файла переменной $file.
#!/bin/bash
suffix=BACKUP--`date +%Y%m%d-%H%M`
for script in *.sh; do
newname="$script.$suffix"
echo "Copying $script to $newname..."
cp $script $newname
done
Результат выполнения этого сценария таков:
$ sh forexample
Copying rhel.sh to rhel.sh.BACKUP--20091210-1708...
Copying sles.sh to sles.sh.BACKUP--20091210-1708...
В раскрытии имени файла все работает в точном соответствии с тем, как написано в командной строке. Другими словами, сначала имя файла раскрывается (т.е. шаблон заменяется существующим именем), а затем уже обрабатывается интерпретатором в развернутом виде.
Аналогично можно ввести имена файла статически, как показано в командной строке:
for script in rosa.sh postinst.sh; do
В действительности любой список имен, содержащих пробельные символы (включая содержимое переменной), обрабатывается как объект циклической конструкции for...in.
Оболочке bash также присуща близость к циклу for из традиционных языков программирования, в которых задается стартовое выражение, инкрементация и условие окончания цикла.
for (( i=0 ; i < $CPU_COUNT ; i++ )) ; do
CPU_LIST="$CPU_LIST $i"
done
На примере следующего сценария иллюстрируется bash-цикл while, который часто применяется для обработки аргументов командной строки и чтения строк файла:
#!/bin/bash
ехес 0<$1
counter=l
while read line; do
echo "$counter: $line"
$((counter++))
done
Результат выполнения этого сценария:
rosa$ sh whileexainple /etc/passwd
1: root:х:0:0:Superuser:/root:/bin/bash
2: bin:x:l:l:bin:/bin:/bin/bash
3: daemon:x:2:2:Daemon:/sbin:/bin/bash
В этом сценарии есть интересные особенности. Оператор ехес переопределяет стандартный выходной поток сценария так, чтобы входные данные считывались из файлов, имена которых должны определяться в соответствии с первым аргументом командной строки. Если окажется, что такой файл не существует, данный сценарий сгенерирует ошибку.
Оператор read в конструкции while на самом деле является встроенным в оболочку, но действует подобно внешней команде. Внешние команды можно также помещать в конструкцию while. Цикл while в такой форме завершится при условии, если внешняя команда возвратит ненулевое значение кода завершения.
Конструкция $((counter++)) обозначает вычисление выражения. Кроме того, оно делает необязательным использование символа "$" для обозначения имен переменных. Удвоенный знак "++" – это оператор постинкремента, знакомый, например, по языку С. Он возвращает значение переменной, с которой он связан, но также увеличивает на 1 это значение.
Выражения $((...)) работают в контексте двойных кавычек, поэтому тело рассмотренного выше цикла можно свернуть до одной строки.
while read line; do
echo "$((counter++)) : $line"
done