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

Цикл Bash For, объясненный примерами

В сценариях оболочки Bash циклы полезны для автоматизации повторяющихся задач. Если вам нужно повторить задачу N раз в вашем сценарии, следует использовать циклы. В bash поддерживаются три типа циклов.

  1. Для цикла
  2. Пока цикл
  3. До цикла

Все три цикла служат одной и той же цели: повторение задачи 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 с экспортом и без него

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