Какова цель ключевого слова «do» в Bash для циклов?


76

Какова цель doключевого слова в forсинтаксисе цикла Bash ? Для меня это кажется излишним.

for i in `seq 1 2`; do echo "hi"; done

Почему синтаксис не такой?

for i in `seq 1 2`; echo "hi"; done

Я уверен, что это действительно соответствует цели. Я просто хочу учиться.

Ответы:


118

Обратите внимание, что этот синтаксис унаследован от оболочки 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"; }

2
Как всегда, полный и совершенный ответ (со ссылкой на zsh) ...
Kiwy

2
Это не "строго необходимо" в любом случае для for; команда может быть завершена символом новой строки или точкой с запятой. Это имеет немного больше смысла для if/ while(первое с thenскорее, чем do), но в принципе те, кто мог бы его пропустить, требовали вложенную оболочку или фигурные скобки для (редкого) использования нескольких команд. Я подозреваю, что настоящая причина, по которой оболочка Bourne делает это, в том, что это делает ALGOL, и мы должны быть рады, что doneэто не записано od.
Random832

4
@ Random832: Это потому, что оно odуже использовалось в качестве названия программы Octal Dump.
user1024

8
Здесь так много, что я не знал. Спасибо!
Легкость гонки с Моникой

1
@mirabilos, for i doэто Bourne и POSIX, но не будет работать в некоторых старых версиях основанных на золе оболочек IIRC. for i in "$@"не будет работать в оболочке Bourne, если $IFSне содержит пробела. for i<newline>doдействительно является наиболее переносимым, если вам нужно рассмотреть очень старые системы BSD. Для получения подробной информации см. In-ulm.de/~mascheck/various/bourne_args
Стефан Шазелас,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.