Циклы

Последнее обновление: 23.03.2024

Циклы позволяют выполнять набор команд многократно в зависимости от некоторого условия. Bash предоставляет следующие типы циклов:

  • for: выполняется определенное количество раз

  • while: выполняется, пока соблюдается указанное условие

  • until: выполняется, пока НЕ соблюдается указанное условие

Цикл while выполняется, пока соблюдается некоторое условие, и имеет следующий синтаксис:

while условие
do
    выполняемые_команды
done

После while указывается условие. И пока оно истинно, выполняется набор команд между операторами do и done. Рассмотрим простейший пример:

#!/bin/bash
# Скрипт, который использует цикл while
num=0
while [ $num -lt 5 ]
do
    echo "num равно $num"
    num=$((num+1))
done

echo "Конец программы"
exit 0

Здесь в качестве условия выступает следующее выражение: [ $num -lt 5 ]. То есть условие истинно, пока переменная num меньше 5 (по умолчанию она равна 0). И пока это условие истинно, выполняются две команды:

echo "num равно $num"
num=$((num+1))

То есть выводим на консоль значение переменной num и увеличиваем ее значение на 1. Таким образом цикл будет выполняться 5 раз. Запустим скрипт:

eugene@Eugene:~$ bash hello
num равно 0
num равно 1
num равно 2
num равно 3
num равно 4
Конец программы
eugene@Eugene:~$ 

until

Цикл until синтаксически похож на while, только обладает обратным действием - выполниет цикл, пока не будет выполняться некоторое условие. Например:

#!/bin/bash
# Скрипт, который использует цикл until
num=0
until [ $num -eq 5 ]
do
    echo "num равно $num"
    num=$((num+1))
done

echo "Конец программы"
exit 0

Здесь те же самые команды цикла, только другое условие - $num -eq 5 , то есть проверяем, равна ли переменная num числу 5. И если равна, скрипт прекращает свою работу.

Результат работы скрипта будет идентичен предыдущему:

eugene@Eugene:~$ bash hello
num равно 0
num равно 1
num равно 2
num равно 3
num равно 4
Конец программы
eugene@Eugene:~$ 

for

Цикл for выполняет набор команд определенное количество раз.

for (( счетчик; условие; приращение_счетчика)); do
набор_команд
done

После слова for в двойных скобках идет заголовок цикла, который состоит из трех частей, разделенных друг от друга точкой с запятой. Первая часть - определение счетчика. Вторая часть - условие, при соблюдение которого будет выполняться цикл. Третья часть - приращение или изменение счетчика.

Далее после заголовка цикла между словами do и done идут команды цикла.

Например, нам надо выполнить некоторое действие 5 раз. Для этого определим следующий скрипт:

#!/bin/bash
# Скрипт, который использует цикл for
for ((i=0; i < 5; i++))
do
    echo "i равно $i"
done

echo "Конец программы"
exit 0

Здесь счетчик представляет переменную i, которая по умолчанию равна 0.

Условие i < 5 выполняется, пока переменная i меньше 5.

После каждого выполнения команд цикла выполняется приращение переменной i на единицу или инкремент - i++

Тело цикла составляет одна команда, которая выводит значение переменной i на консоль:

echo "i равно $i"

Таким образом, перед выполнением цикла переменная i устанавливается в 0. Далее проверяется условие i < 5. Если i меньше 5, то выполняется команда echo "i равно $i". И после ее выполнения выполняется увеличение переменной i на 1 (i++). Далее все повторяется - снова проверяется условие и выполняются команды цикла. Если же условие не верно - i равна или больше 5. То цикл прекращает свою работу. И в данном случае при выполнении скрипта мы получим следующий результат:

eugene@Eugene:~$ bash hello
i равно 0
i равно 1
i равно 2
i равно 3
i равно 4
Конец программы
eugene@Eugene:~$

Для определения условий можно использовать стандартные операторы сравнения: < (меньше чем), > (больше чем), <= (меньше чем или равно), > (больше чем или равно), == (равно), != (не равно).

Для приращения счетчика цикла можно использовать операторы инкремента (увеличения на 1) ++, декремента (уменьшения на 1) --, увеличение с присвоением +=, уменьшение с присвоением -=. Например, увеличим счетчик на 2:

for ((i=0; i < 5; i=i+2))
do
    echo "i равно $i"
done

Или уменьшение на произвольное число:

#!/bin/bash
# Скрипт, который использует цикл for
for ((i=10; i > 0; i=i-2))
do
    echo "i равно $i"
done

echo "Конец программы"
exit 0

Еще один пример - выполнение цикла, пока счетчик не станет равным 0:

#!/bin/bash
# Скрипт, который использует цикл for
for ((i=10; i != 0; i--))
do
    echo "i равно $i"
done

echo "Конец программы"
exit 0

for..in

Особая форма цикла for - for..in позволяет перебрать набор значений:

for переменая in набор_значений
do
    набор_команд
done 

Цикл for проходит по набору значений и каждое значение помещает в переменную. Между do и done также помещаются команды, которые выполняются для каждого перебираемого значения из набора значений.

Например, мы можем перебрать текстовый файл по отдельной строке

#!/bin/bash
for i in `cat /etc/passwd`
do
    echo $i
done
exit 0

Для примера здесь перебираются все строки из файла "/etc/passwd". Для получения строк применяется команда cat /etc/passwd, то есть вывод этой команды фактически представляет набор строк. Каждая строка помещается в переменную i. И для каждой строки выполняется команда echo $i

Другой пример - нам надо пропинговать некоторые адреса из локальной сети. Для этого определим следующий скрипт:

#!/bin/bash
for i in $@
do
    ping -c 1 192.168.1.$i
done
exit 0

Обратите внимание на использование $@. Этот идентификатор позволяет обратиться ко всем аргументам, которые были указаны при запуске скрипта, независимо от их количества. А, используя for, можно перебрать каждый из этих аргументов. Так, запустим скрипт, передав ему диапазон адресов

eugene@Eugene:~$ bash hello 1 2 3 4 5
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.

--- 192.168.1.1 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.

--- 192.168.1.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

PING 192.168.1.3 (192.168.1.3) 56(84) bytes of data.

--- 192.168.1.3 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

PING 192.168.1.4 (192.168.1.4) 56(84) bytes of data.

--- 192.168.1.4 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

PING 192.168.1.5 (192.168.1.5) 56(84) bytes of data.
64 bytes from 192.168.1.5: icmp_seq=1 ttl=62 time=67.8 ms

--- 192.168.1.5 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 67.823/67.823/67.823/0.000 ms
eugene@Eugene:~$ 

В данном случае скрипту передается набор 1 2 3 4 5, и весь этот набор доступен через $@. При переборе в цикле каждое число из этого набора помещается в переменную i, которая используется для пинга адреса.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850