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

Циклы Bash while и Until объяснены примерами

Это продолжение статьи о цикле bash, в которой в предыдущей статье мы объясняли цикл for. В этой статье мы рассмотрим еще два цикла bash, а именно: цикл while и until.

Цикл while чаще всего используется, когда вам нужно прочитать содержимое файла и продолжить его обработку. Чтение и запись в файл — распространенные операции при написании сценариев bash. Мы увидим, как читать файлы с помощью цикла while.

У нас уже есть очень подробная статья о том, как писать в файл с помощью операторов перенаправления.

  • Перенаправление Bash, объясненное примерами

Функциональность цикла while аналогична циклу for. Цикл for перебирает список элементов и запускает блок кода N несколько раз. Здесь, в цикле while, сначала оценивается условие, и если условие истинно, блок кода будет выполняться до тех пор, пока условие не станет ложным.

1. Цикл «Пока»

Ниже приведен синтаксис цикла while. Цикл начинается с ключевого слова " while", за которым следует условие, истинность которого должна быть оценена. Между блоками do и done будут размещены ваши коды, которые будут повторяться N количество раз.

while [[ condition ]]
do
  Command 1
  Command 2
  ....
  Command 3
done

ПРИМЕР 1. Оценка и повторение

Взгляните на приведенный ниже пример. Здесь я создал переменную "NUM=5" и мое условие ($NUM -ne 0): цикл будет выполнен, если переменная NUM не равен нулю.

NUM=5
while [[ $NUM -ne 0 ]]
do
  printf "Value of NUM = $NUM \n"
  ((--NUM))
done

Оценивайте и повторяйте

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

((++NUM))  → Increment NUM variable by 1, similar to running NUM=$(( $NUM + 1 ))
((--NUM))  → Decrement NUM variable by 1, similar to running NUM=$(( $NUM - 1 ))

ПРИМЕР 2. Бесконечные циклы

Бесконечный цикл — это когда ваше условие всегда оценивается как истинное, и цикл никогда не завершается.

Чтобы создать бесконечные циклы, вы можете использовать встроенное в bash ключевое слово true. Кроме того, используйте команду "sleep" при тестировании бесконечных циклов, которая даст вам контроль над остановкой сценария, иначе ваш экран будет заполнен выводами с быстрой прокруткой.

NUM=0
while true
do
  printf "Value of NUM = $NUM \n"
  ((++NUM))
  sleep 2
done

Бесконечный цикл while

ПРИМЕР 3. Внутренний разделитель полей (IFS)

IFS — это специальная переменная оболочки, которая определяет, как обрабатывать границы слов. По умолчанию IFS настроен на пробел, табуляцию и символ новой строки. Откройте терминал и выполните следующие команды:

var1="foo:bar foo bar"
for val in $var1
do
  echo $val
done 

IFS по умолчанию

Посмотрите на результат. Цикл for перебирает строку, и именно IFS определяет границы слов и рассматривает пробел как разделитель полей.

Теперь снова запустите приведенный ниже код. Здесь для IFS установлено значение двоеточие.

var1="foo:bar foo bar"
IFS=":"
for val in $var1
do
  echo $val
done

Пользовательский IFS

Из приведенного выше вывода вы можете видеть, что в качестве границы слова используется настраиваемое двоеточие-разделитель полей. Вы можете вернуть IFS в состояние по умолчанию, выполнив команду unset.

unset IFS

ПРИМЕР 4. Чтение файла с использованием цикла while

Цикл while рекомендуется использовать, если вы хотите прочитать файл построчно и обработать его.

Создайте новый файл с именем test.txt, используя следующий контент. После строки 2 есть пустая строка, показывающая, как обрабатываются пустые строки.

14:00 Brighton v Leicester
14:00 West Ham v Man Utd

16:30 Spurs v Chelsea

Мы будем использовать команду read, которая принимает входные данные от перенаправления и сохраняет их в переменной вместе с оператором перенаправления ввода, где имя файла будет перенаправлено в цикл while. Команда read будет использовать IFS по умолчанию для установки границы разделения слов.

while read line
do
  echo $line
done < test.txt

Прочитайте файл, используя цикл while

В приведенном выше примере файл test.txt перенаправляется в цикл while, а команда read считывает построчно и сохраняет его в переменной "строка" и далее обрабатывается в цикле. Пустые строки не пропускаются при использовании этого метода, и это не то поведение, которое вам может понадобиться. Поэтому вам нужно явно пропускать пустые строки.

Существует несколько вариантов удаления пустых строк из входного файла. Вы можете использовать sed, awk, условные операторы и т. д. Я предпочитаю использовать для очистки и awk, и sed. поднимите пустые строки перед их зацикливанием с помощью цикла while.

USING SED
sed -i '/^[[:space:]]*$/d' test.txt
14:00 Brighton v Leicester
14:00 West Ham v Man Utd
16:30 Spurs v Chelsea
USING AWK
awk 'NF' test.txt

Удалите пустые строки с помощью sed и awk

Как видно из предыдущих примеров, вы можете изменить IFS в зависимости от того, как вы хотите читать файл. Например, если вы работаете с файлом CSV, в качестве разделителя можно установить запятую. Я изменил тот же входной файл в формате CSV.

14:00,Brighton,Leicester
14:00,West Ham,Man Utd
16:30,Spurs,Chelsea

В приведенном ниже примере IFS имеет значение запятой (IFS=","), и каждое поле будет храниться в отдельной переменной (time, team1, team2).

while IFS="," read time team1 team2
do
   echo "$team1 is playing against $team2 at $time"
done < test.txt

Чтение CSV-файлов

ПРИМЕР 5. Циклическое управление потоком данных с помощью Break и Continue.

Если вы читали нашу статью о цикле bash for, возможно, вы знаете, для чего используются break и continue. И Break, и continue — это встроенные ключевые слова bash, которые помогут вам контролировать ход вашего цикла.

Ключевое слово «break» позволит полностью выйти из цикла и передать управление следующей команде сценария. В приведенном ниже примере. Когда NUM равно трем, выход из цикла будет выполнен командой break.

NUM=5
while [[ $NUM -ne 0 ]]
do
  printf "Value of NUM = $NUM \n"
  if [[ $NUM -eq 3 ]]
  then
    break
  fi   
((--NUM))
done

Цикл while с оператором прерывания

Ключевое слово «continue» пропустит текущую итерацию, вернет управление циклу while и начнет следующую итерацию.

NUM=0
while [[ $NUM -lt 5 ]]
do
 ((++NUM))
 if [[ $NUM -eq 3 ]]
 then
   continue
 fi
 printf "Value of NUM = $NUM \n"  
done

Цикл while с оператором continue

2. До цикла

Цикл until является полной противоположностью цикла while. Цикл while оценивает условие как истинное для выполнения блока кода, а цикл until оценивает условие как ложное для выполнения цикла.

Синтаксис такой же, как у цикла while, но вместо ключевого слова while будет использоваться until.

until [[ condition ]]
do
  Command 1
  Command 2
  ....
  Command 3
done

В приведенном ниже примере вы можете видеть, что цикл until оценивает переменную NUM как большую, чем равную пяти. Это неверно, поскольку NUM установлено в ноль и будет увеличиваться в последующих итерациях с использованием ((++NUM)). Таким образом, когда NUM равно пяти, условие считается истинным, и цикл until прекратит выполнение.

NUM=0
until [[ $NUM -ge 5 ]]
do
  echo $NUM
  ((++NUM))
done

До цикла

Чтобы создать бесконечные циклы, вы можете использовать ключевое слово false.

NUM=0
until false
do
  echo $NUM
  ((++NUM))
done

Чтобы управлять потоком цикла, вы можете использовать ключевые слова break и continue, как показано в разделе цикла while выше.

Заключение

В этой статье мы увидели, как использовать циклы while и until в сценариях bash. Цикл Until используется реже всего по сравнению с циклами for и while, но он предназначен для принятия решения о вашем сценарии и о том, какие типы цикла необходимы. Будьте уверены в использовании всех трех петель.

Если у вас есть какие-либо вопросы или отзывы, сообщите нам об этом в разделе комментариев ниже.

Связанное чтение:

  • Скрипты Bash: цикл выбора с примерами
  • Скрипты Bash: функции, поясняемые примерами
  • Скрипты Bash: переменные, поясняемые примерами
  • Команда Bash Echo с примерами для Linux
  • Руководство по Bash Heredoc для начинающих
  • Как повторять команду до успешного выполнения в Linux
  • Разница между определением переменных Bash с экспортом и без него

Статьи по данной тематике