Цикл Bash For, объясненный примерами
В сценариях оболочки Bash циклы полезны для автоматизации повторяющихся задач. Если вам нужно повторить задачу N раз в вашем сценарии, следует использовать циклы. В bash поддерживаются три типа циклов.
- Для цикла
- Пока цикл
- До цикла
Все три цикла служат одной и той же цели: повторение задачи N раз, когда условие удовлетворено, но с различиями в том, как они определяются и используются для достижения результата.
В этой статье основное внимание будет уделено циклу for в сценариях Bash. О двух других циклах мы узнаем в нашем следующем руководстве.
Для синтаксиса цикла
Понимание синтаксиса очень важно, прежде чем писать свой первый цикл for
.
for NAME in [ LIST OF ITEMS ]
do
Command 1
Command 2
.....
Command N
done
Давайте разберем его и посмотрим, что он делает.
- Начните с ключевого слова
"for"
, за которым следует имя переменной. - Ключевое слово
"in"
позволяет получить список элементов и сохранить его в переменной для каждой итерации. - Ключевые слова
"do"
и"done"
отмечают начало и конец блока цикла, и команда должна быть написана внутри do и Done. - Строгих правил отступов нет, но для лучшей читаемости используйте 2 пробела или tab(4). Будьте последовательны в использовании пробела или табуляции во всем сценарии.
Вы также можете создать одну строку для циклов. Создайте цикл for
в терминале и нажмите клавишу со стрелкой вверх, и вы увидите, что bash автоматически преобразует его в однострочный цикл.
for NAME in [ LIST OF ITEMS]; do COMMANDS ; done
Пример 1. Работа со списком элементов
Начнем с простого примера.
Из предыдущего раздела вы, возможно, поняли, что цикл for
принимает список элементов. Список элементов может быть чем угодно: строками, массивами, целыми числами, диапазонами, выводом команды и т. д.
Откройте терминал и запустите следующий фрагмент кода.
N=1
for val in Welcome To Ostechnix
do
echo "Iteration $N → $val"
((++N))
done
Давайте разберемся.
"Добро пожаловать в Ostechnix"
— это список элементов, передаваемых в циклfor
, и каждое слово будет выбрано как отдельная итерация и сохранено в переменной (val
).- Переменную можно назвать как угодно. Здесь я называю его
val
. - В списке три элемента, поэтому в
цикле for
будет три итерации, и каждый раз будет печататься значение переменнойval
. - Команда ((
++N
)) будет действовать как счетчик и увеличивать значение переменнойN
, чтобы его можно было напечатать в>эхо
.
для примера цикла
Теперь после запуска указанной выше команды for цикл
нажмите клавишу со стрелкой вверх на терминале, и вы увидите, что многострочный for цикл
преобразуется в одну строку для цикла.
Пример 2. Работа с диапазонами
Возможно, вы захотите запустить цикл for
N количество раз, для этого вы можете использовать встроенный генератор последовательностей bash "{x..y[. .incr]}"
, который будет генерировать последовательность чисел.
X
=начальное целое значениеY
=конечное целое значениеIncr
=необязательное целочисленное значение, которое увеличивает целые числа.
Допустим, вы хотите запустить цикл пять раз, тогда вы можете использовать следующий фрагмент.
for rng in {1..5}
do
echo "Value is == $rng"
done
для цикла с диапазоном
Вы также можете использовать дополнительный параметр приращения, который будет выполнять пошаговое приращение.
Взгляните на фрагмент ниже, где дано приращение три. Это сгенерирует последовательность из единицы и сделает шаг с шагом в три до конечного значения десять.
for rng1 in {1..10..3}
do
echo "Value is == $rng1"
done
Увеличение значений в цикле for
Пример 3. Выполнение команд
Вы можете запускать любые команды, которые получают список элементов, которые будут обработаны с помощью цикла for
. Команда должна быть заключена в галочки «``
» или в скобки «$()
».
В приведенном ниже примере я запускаю команду, которая получит идентификатор процесса и отфильтрует последние пять процессов. Цикл for теперь будет перебирать каждый идентификатор процесса.
for list in $(ps -ef | awk {' print $2 '} | tail -n 5)
do
echo $list
done
Запуск команды в цикле for
Пример 4. Цикл по элементам массива
В сценариях реального времени вы сохраните некоторые значения в массивах и попытаетесь пройти по массиву для дальнейшей обработки.
Прежде чем понять, как перебирать массив, вам необходимо понять поведение двух специальных переменных ( $@
и $*
). Обе это специальные переменные, которые используются для доступа ко всем элементам массива.
Запустите следующий фрагмент кода в терминале. Создается массив X, и когда я пытаюсь напечатать все значения ($X
), как я печатаю переменные, он просто возвращает первое значение из массива.
X=( 16 09 2021 "Thursday Third Week" )
echo $X
16
Печать элементов массива
Чтобы получить доступ ко всем элементам массива, вам нужно использовать либо $@
, либо $*
. Синтаксис доступа к значениям массива будет следующим.
echo ${X[@]}
16 09 2021 Thursday Third Week
echo ${X[*]}
16 09 2021 Thursday Third Week
Расширение массива
Теперь используйте это с циклом for
для перебора значений массива.
X=( 16 09 2021 "Thursday Third Week" )
for items in ${X[@]}
do
echo $items
done
Перебор элементов массива
Взгляните на приведенный выше вывод. Этот вывод кажется неверным, поскольку строку (четверг, третья неделя) внутри массива следует рассматривать как одно значение. Но здесь каждый элемент рассматривается как отдельный элемент.
Это поведение по умолчанию при использовании $@
или $
. Чтобы обойти эту проблему, заключите переменную расширения массива ($@
или $
) в двойные кавычки.
for items in "${X[@]}"
do
echo $items
done
Использование двойных кавычек с $@ в цикле for
При использовании двойных кавычек $@
и $*
ведут себя по-разному. В то время как $@
расширяет массив до каждого элемента в виде массива, как показано в примере выше, $*
расширяет весь массив как одно значение.
for items in "${X[*]}"
do
echo $items
done
Использование двойных кавычек с $* в цикле for
Внимание: И $@
, и $*
ведут себя одинаково, если только они не заключены в двойные кавычки. Старайтесь избегать $*
, если в этом нет необходимости.
Пример 5. Стиль C для синтаксиса цикла
Bash также предлагает синтаксис цикла
в стиле c. Если вы используете язык C, то этот синтаксис не будет для вас новым.
Вместо перебора списка вы будете оценивать условие, и если условие истинно, команды внутри цикла будут выполнены.
В этом синтаксисе вам необходимо понимать три параметра.
- Переменная. Переменная инициализируется только один раз при запуске цикла.
- Условие. Для выполнения цикла условие должно быть истинным, иначе цикл не запустится.
- Счетчик — увеличивает значение переменной.
Каждый параметр должен быть разделен точкой с запятой (;
) и заключен в двойные скобки, как показано ниже.
for (( variable; condition; counter ))
do
Command 1
Command 2
Command N
done
Взгляните на приведенный ниже пример високосного года.
- Переменная
YEAR=2010
будет инициализирована первой. - Условие
YEAR<=20
будет оценено, и если оно истинно, код междуdo
и блокомdone
будет выполнен. - Счетчик
YEAR++
увеличит год на единицу. Пока переменнаяYEAR
не будет увеличена до2020
, цикл будет повторяться. - Внутри блоков
do
иdone
записывается условный оператор, проверяющий, является ли год високосным или нет.
for ((YEAR=2010; YEAR<=2020; YEAR++))
do
if [[ $(expr $YEAR % 4) -eq 0 ]]
then
echo "$YEAR = leap year"
else
echo "$YEAR = not a leap year"
fi
done
Найти високосный год с помощью оператора цикла for
Пример 6. Использование операторов Break, Continue
Есть два встроенных ключевых слова bash, которые используются для управления потоком ваших циклов.
- Break — выход из цикла и пропуск всех ожидающих итераций.
- Продолжить — пропустить текущую итерацию и передать управление обратно в цикл for для выполнения следующей итерации.
Чтобы проверить, встроены ли они в bash, используйте команду type
:
type break continue
break is a shell builtin
continue is a shell builtin
Давайте вкратце посмотрим, как и где можно использовать функции Break и продолжения.
Я использую тот же код, что и в предыдущем разделе, чтобы найти високосный год. В данном случае мне просто нужно указать первый високосный год между 2010 и 2020 годами. Если этот год будет найден, мой цикл может выйти.
for ((YEAR=2010; YEAR<=2020; YEAR++))
do
if [[ $(expr $YEAR % 4) -eq 0 ]]
then
echo "$YEAR = leap year"
break
else
echo "$YEAR = not a leap year"
fi
done
Оператор Break с циклом for
Из приведенного выше вывода вы можете видеть итерации for цикла
, и когда найден первый високосный год 2012, считывается оператор break
, цикл завершается и управление возвращается. к терминалу.
Теперь я изменяю тот же код для оператора "continue"
. Оператор continue
при его интерпретации пропустит текущую итерацию, то есть любой код, который идет после оператора continue, и передаст управление обратно в цикл for
для запуска следующей итерации.
for ((YEAR=2010; YEAR<=2020; YEAR++))
do
if [[ $(expr $YEAR % 4) -eq 0 ]]
then
echo "$YEAR = leap year"
else
continue
echo "$YEAR = not a leap year"
fi
done
Продолжить оператор с циклом for
На изображении выше вы можете видеть, что есть оператор echo, который пропускается оператором continue.
Пример 7. Использование истинного оператора
Когда вы создаете циклы или условные операторы, вы не можете оставить блок кода пустым. Bash выдаст синтаксическую ошибку.
Ошибка синтаксиса
Пустые условные операторы
Взгляните на оба изображения выше. На первом изображении я создал цикл for
, но между do
и done
нет команд. Аналогично во втором изображении я оставил предложение else пустым. В обоих случаях bash не принимает пустые блоки и выдает синтаксические ошибки.
Вы можете использовать встроенное в bash ключевое слово “true”
, которое всегда будет устанавливать код выхода на 0 (успех).
type true
true is a shell builtin
Таким образом, вы оставляете блок кода пустым, а bash не выдает никаких ошибок.
Настоящее ключевое слово
Заключение
В этом руководстве мы начали с знакомства с циклами и синтаксисом цикла for
, а также со стилем C. Мы также увидели, как использовать bash for циклы в различных условиях вместе с операторами управления циклом Break и continue. Ознакомьтесь с нашим следующим руководством, чтобы узнать о циклах Bash While
и Until
с примерами.
- Скрипты Bash: циклы while и Until с примерами
Связанное чтение:
- Скрипты Bash: цикл выбора с примерами
- Скрипты Bash: функции, поясняемые примерами
- Сценарии Bash: переменные, поясняемые примерами
- Команда Bash Echo с примерами для Linux
- Руководство по Bash Heredoc для начинающих
- Перенаправление Bash, объясненное примерами
- Разница между определением переменных Bash с экспортом и без него