делать ... пока или делать ... пока в сценарии оболочки POSIX

16

Существует хорошо известный while condition; do ...; doneцикл, но есть ли do... whileцикл стиля, который гарантирует хотя бы одно выполнение блока?

Шон Дж. Гофф
источник
Большое спасибо, Шон, я не ожидал, что ответ станет таким быстрым. Итак: спасибо за выбор.

Ответы:

15

Очень универсальная версия do ... whileимеет следующую структуру:

while 
      Commands ...
do :; done

Примером является:

#i=16
while
      echo "this command is executed at least once $i"
      : ${start=$i}              # capture the starting value of i
      # some other commands      # needed for the loop
      (( ++i < 20 ))             # Place the loop ending test here.
do :; done
echo "Final value of $i///$start"
echo "The loop was executed $(( i - start )) times "

Поскольку он установлен (значение не установлено i), цикл выполняется 20 раз.
Не комментируя строку, которая установлена iв 16 i=16, цикл выполняется 4 раза.
Для i=16, i=17, i=18и i=19.

Если в той же точке (начало) установлено значение i (скажем, 26), команды все равно выполняются в первый раз (до тех пор, пока не будет проверена команда прерывания цикла).

Тест на некоторое время должен быть правдивым (статус выхода 0).
Тест следует поменять местами до цикла, т. Е. Быть ложным (состояние выхода не 0).

Версия POSIX нуждается в изменении нескольких элементов для работы:

i=16
while
       echo "this command is executed at least once $i"
       : ${start=$i}              # capture the starting value of i
       # some other commands      # needed for the loop
       i="$((i+1))"               # increment the variable of the loop.
       [ "$i" -lt 20 ]            # test the limit of the loop.
do :;  done
echo "Final value of $i///$start"
echo "The loop was executed $(( i - start )) times "

./script.sh
this command is executed at least once 16
this command is executed at least once 17
this command is executed at least once 18
this command is executed at least once 19
Final value of 20///16
The loop was executed 4 times 

источник
Имейте в виду, что если вы используете set -eчто-то неуспешное в блоке условия while, это не остановит выполнение: например, set -e; while nonexistentcmd; true; do echo "SHiiiiit"; exit 3; done-> случится дерьмо. Таким образом, если вы используете это, вы должны быть очень осторожны с обработкой ошибок, то есть объединять все команды с &&!
Тимо
17

Не существует цикла do ... while или do ... before, но то же самое можно выполнить следующим образом:

while true; do
  ...
  condition || break
done

до тех пор, пока:

until false; do
  ...
  condition && break
done
Шон Дж. Гофф
источник
Вы можете использовать любую из линий разрыва с любым из циклов - пока true или пока false просто означает «навсегда». Я понимаю, что в некотором роде сохраняется время или время, чтобы иметь условие «счастливый выход» или «грустный выход».
android.weasel