Поиск по сайту:

Учебник: циклы Bash: for, while и until


Большинство языков программирования поддерживают различные формы зацикливания строк кода. Bash изначально поддерживает циклы «пока», циклы «до» и наиболее известные циклы «для». В этой статье представлены и обсуждаются все три.

Что такое циклы Баша?

Чтобы определить это немного лучше, мы должны начать с вопроса что такое циклы. Циклы — это конструкция языка программирования, позволяющая разработчику повторять (то есть зацикливать) определенные части или весь код внутри такого определения цикла. Теперь легко определить Bash Loops как любую конструкцию языка программирования циклов, используемую в Bash!

Bash изначально поддерживает циклы «для», «до» и «пока». У каждого из них есть свои преимущества, но вы уже можете понять их значение, просто взглянув на идиому основного слова. Например, «пока» естественно заставляет задуматься о том, чтобы «сделать что-то до», и это действительно то, что делает цикл Bash «до»; он зацикливает определенное количество (или весь) кода до тех пор, пока не будет выполнено определенное условие.

Точно так же циклы «пока» продолжают работать до тех пор, пока условие не перестанет быть истинным. Наконец, циклы for зацикливаются, например, определенное количество раз, подобно тому, как мы пишем «for 70 times, do…». Это помогает нам логически понять уникальные функции, которые предоставляет нам каждый цикл, и реализовать более читаемый код.

для основанных циклов Bash

Для целей этой статьи мы рассмотрим новую форму определения циклов Bash for loop. Несколько более старое и менее современное определение цикла for в Bash может, например, выглядеть примерно так: for i in $ (seq 1 5); эхо $i; сделано. Давайте сравним это с более чистым, лучше структурированным, современным циклом for:

for ((i=1;i<=5;i++)); do echo $i; done

Этот простой однострочник на основе for на основе Bash (термин, часто используемый в кругах Linux/Bash для концептуализации мини-скрипта, написанного на одной строке) будет печатать числа от 1 до 5 в последовательном порядке. Мы устанавливаем начальное значение для переменной i ($i), присваивая значение 1 тому же самому, что и первая часть нашего < определение цикла i>for, заканчивающееся разделителем ;.

Затем мы указываем, что мы можем перейти только к «меньше или равно пяти», используя i<=5. Затем мы указываем, что должно произойти в конце каждого раунда, а именно увеличить переменную i на единицу, или, в общеупотребительном (в том числе в языке C++, например) сокращении кодирования, это отображает как i++.

Наконец, мы указываем начало нашего кода цикла с помощью do, то есть после завершения нашего определения цикла for, аналогично завершению любого другого оператора, с помощью ; перед do. Мы также указываем конец нашего кода цикла, используя done, и мы выводим (распечатываем) значение нашей переменной i между сделать и сделать.

Также обратите особое внимание на то, что само предложение do не завершается ;, и это приведет к ошибке. Считайте do префиксом того, что нужно сделать, и это имеет больше смысла. Возможно, это одна из причин, по которой иногда лучше помещать вещи в многострочный скрипт, поскольку do может просто быть последним словом в строке.

Даже при определении других типов циклов мы по-прежнему будем поддерживать предложения do и done и всегда будем завершать определение нашего цикла (т. е. до того, как do ) с помощью ;, а также завершение конца каждого отдельного оператора в нашем определении цикла do...done с помощью ; .

Давайте поместим это в небольшой скрипт, чтобы лучше понять, как все может работать таким образом:

#!/bin/bash

for ((i=1;i<=10;i+=2)); do 
  echo $i
done

Сделав скрипт исполняемым с помощью chmod +x test.sh, мы выполняем то же самое. В сценарий было внесено несколько небольших изменений. Обратите внимание, как на этот раз мы каждый раз увеличиваем переменную i на два. Это делается с помощью другого сокращения кодирования, а именно i+=2, которое можно прочитать как увеличить i на два. Можно также написать i=i+2 в том же месте, и это работает точно так же.

Мы видим, что начинаем с 1 и увеличиваем на 2 каждый раз, когда проходим цикл, заканчивая на 9. Причина, по которой он заканчивается на 9, заключается в том, что максимальное значение равно 10. Таким образом, после 9 следующим значением будет 11, что больше, чем 10, и поэтому оно не отображается/зацикливается.

Обратите также внимание на то, как ; был удален после эхо-строки. Это потому, что нет необходимости завершать конец оператора, если вместо этого есть ситуация/символ конца строки. Это случай здесь; у нас нет никакой другой команды после echo $i, и строка немедленно заканчивается (пробелы в конце строки тоже подойдут, принцип заключается в том, чтобы просто не иметь другой команды, если эта новая команда имеет префикс (и предыдущий завершается) с помощью ;).

в то время как на основе циклов Bash

Давайте теперь посмотрим на цикл Bash — используя то же определение цикла do...done, мы можем определить цикл Bash на основе while, который будет работать до тех пор, пока заданное условие истинно.

i=1; while [ $i -le 5 ]; do echo $i; i=$[ i + 1 ]; done

В этом примере мы делаем то же самое, что и в нашем первом примере с циклом for. Хотя определение выглядит более сложным (и, следовательно, цикл for может лучше подходить для этого конкретного случая использования), интересно посмотреть, как мы можем определить цикл while в так же.

Здесь мы сначала устанавливаем нашу переменную i вручную в отдельной команде, оканчивающейся ;, на 1. Затем мы запускаем цикл while, в котором мы устанавливаем условие, очень похожее на определение оператора if (в конце этой статьи есть ссылка на статью о операторах if, если вы хотите узнать больше), где мы проверяем, меньше или равно значение переменной i (-le), затем < я>5.

После этого у нас есть наш обычный блок do...done, в котором мы выводим нашу переменную, а затем в новом операторе вручную увеличиваем значение нашего i на единицу в математических вычислениях, как определено в идиомах вычислений $[...] Bash. Теперь давайте проверим цикл until на основе Bash.

до тех пор, пока не будут созданы циклы Bash

Вооружившись тем, что мы уже узнали, теперь мы можем более легко оценить следующий цикл Bash на основе until:

i=1; until [ $i -gt 5 ]; do echo $i; i=$[ i + 1 ]; done

Здесь мы ищем, чтобы условие i больше 5 стало истинным. До этого времени (т.е. цикл на основе until) мы будем печатать (используя echo) нашу переменную i и увеличивать ее на единицу, так к нашему предыдущему примеру на основе while.

Мы видим, что синтаксис команды until очень похож на команду while. Также обратите внимание, что, в отличие от команды на основе for, эти команды ищут либо условие true для сохранения (с while), либо условие for. истинное условие для начала (с до). Это также позволяет использовать другие команды, которые могут возвращать вывод true/false, например, grep -q:

echo 1 > a
while grep -q '1' ./a; do echo 'yes'; sleep 5; done

Здесь мы добавляем число 1 в файл с именем a и проверяем наличие числа 1 в этом файле с помощью grep -q (тихий grep). Мы продолжаем делать это (т. е. пока), пока это не перестанет быть правдой. Пока это правда, мы печатаем текст yes и приостанавливаем цикл на пять секунд с помощью sleep 5. Обратите внимание, что каждая команда снова завершается с помощью ;.

Примерно через 17 секунд мы прерываем наш скрипт, используя CTRL+c, который является универсальным методом для остановки запущенного процесса в Bash (кроме более сильного и эффективного CTRL+z, который немедленно приостанавливает процесс, но это для другой статьи!)

Подведение итогов

В этой статье мы рассмотрели циклы «for», «while» и «until», изначально доступные в Bash. Если вас интересуют дополнительные сведения о Bash, взгляните на условное тестирование в Bash: if, then, else, функции elif и Bash и локальные переменные.

Наслаждайтесь!