Обратите внимание, что этот синтаксис унаследован от оболочки Bourne.
После имени переменной у вас может быть либо in
явно заданный список элементов, либо do
цикл по позиционным параметрам.
for i in 1 2 3
do
echo "$i"
done
Или же
set 1 2 3
for i do
echo "$i"
done
Наличие do
в обоих случаях (даже если в первом случае это не является строго обязательным) обеспечивает более согласованный синтаксис. Это также согласуется с циклами while
/, until
где do
это необходимо.
while
cmd1
cmd2
do
cmd3
cmd4
done
Вам нужно do
сказать, где заканчивается список команд условия .
Обратите внимание, что оболочка Bourne не поддерживается for i; do
. Этот синтаксис также не использовался в POSIX до выпуска стандарта 2016 года ( for i do
всегда был POSIX; см. Соответствующую ошибку группы в Остине ).
zsh
имеет несколько сокращенных форм, таких как:
for i in 1 2 3; echo $i
for i (1 2 3) echo $i
for ((i=1;i<=3;i++)) echo $i
Или поддержка более чем одной переменной:
for i j (1 a 2 b) echo $i $j
(хотя вы не можете использовать in
или do
как имя переменной вместо j
выше).
Даже если это редко документировано, большинство Bourne-подобных оболочек (Bourne, ksh, bash, zsh, not ash
или yash
) также поддерживают:
for i in 1 2 3; { echo "$i";}
Оболочка Bourne ksh
и zsh
(но не bash
) также поддерживают:
for i { echo "$i"; }
Хотя bash
, ksh
и zsh
(но не Bourne оболочки) поддержка:
for i; { echo "$i"; }
Все (Bourne, bash
, ksh
, zsh
) поддержка:
for i
{ echo "$i";}
ksh93
, bash
, zsh
Поддержка:
for ((i=1;i<=3;i++)) { echo "$i"; }
for
; команда может быть завершена символом новой строки или точкой с запятой. Это имеет немного больше смысла дляif
/while
(первое сthen
скорее, чемdo
), но в принципе те, кто мог бы его пропустить, требовали вложенную оболочку или фигурные скобки для (редкого) использования нескольких команд. Я подозреваю, что настоящая причина, по которой оболочка Bourne делает это, в том, что это делает ALGOL, и мы должны быть рады, чтоdone
это не записаноod
.od
уже использовалось в качестве названия программы Octal Dump.for i do
это Bourne и POSIX, но не будет работать в некоторых старых версиях основанных на золе оболочек IIRC.for i in "$@"
не будет работать в оболочке Bourne, если$IFS
не содержит пробела.for i<newline>do
действительно является наиболее переносимым, если вам нужно рассмотреть очень старые системы BSD. Для получения подробной информации см. In-ulm.de/~mascheck/various/bourne_args