Циклы 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 с экспортом и без него