Циклы командная строка linux

Циклы командная строка linux

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

Цикл — это блок команд, который исполняется многократно до тех пор, пока не будет выполнено условие выхода из цикла.

Это одна из основных разновидностей циклов. И она значительно отличается от аналога в языке C.

На каждом проходе цикла, переменная-аргумент цикла arg последовательно, одно за другим, принимает значения из списка list.

for arg in "$var1" "$var2" "$var3" . "$varN" # На первом проходе, $arg = $var1 # На втором проходе, $arg = $var2 # На третьем проходе, $arg = $var3 # . # На N-ном проходе, $arg = $varN # Элементы списка заключены в кавычки для того, чтобы предотвратить возможное разбиение их на отдельные аргументы (слова).

Элементы списка могут включать в себя шаблонные символы.

Есл ключевое слово do находится в одной строке со словом for, то после списка аргументов (перед do) необходимо ставить точку с запятой.

Пример 10-1. Простой цикл for

#!/bin/bash # Список планет. for planet in Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун Плутон do echo $planet done echo # Если 'список аргументов' заключить в кавычки, то он будет восприниматься как единственный аргумент . for planet in "Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун Плутон" do echo $planet done exit 0

Пример 10-2. Цикл for с двумя параметрами в каждом из элементов списка

#!/bin/bash # Список планет. # Имя кажой планеты ассоциировано с расстоянием от планеты до Солнца (млн. миль). for planet in "Меркурий 36" "Венера 67" "Земля 93" "Марс 142" "Юпитер 483" do set -- $planet # Разбиение переменной "planet" на множество аргументов (позиционных параметров). # Конструкция "--" предохраняет от неожиданностей, если $planet "пуста" или начинается с символа "-". # Если каждый из аргументов потребуется сохранить, поскольку на следующем проходе они будут "забиты" новыми значениями, # То можно поместить их в массив, # original_params=("$@") echo "$1 в $2,000,000 миль от Солнца" #----две табуляции---к параметру $2 добавлены нули done # (Спасибо S.C., за разъяснения.) exit 0

В качестве списка, в цикле for, можно использовать переменную.

Пример 10-3. Fileinfo: обработка списка файлов, находящегося в переменной

#!/bin/bash # fileinfo.sh FILES="/usr/sbin/privatepw /usr/sbin/pwck /usr/sbin/go500gw /usr/bin/fakefile /sbin/mkreiserfs /sbin/ypbind" # Список интересующих нас файлов. # В список добавлен фиктивный файл /usr/bin/fakefile. echo for file in $FILES do if [ ! -e "$file" ] # Проверка наличия файла. then echo "Файл $file не найден."; echo continue # Переход к следующей итерации. fi ls -l $file | awk '< print $8 " размер: " $5 >' # Печать 2 полей. whatis `basename $file` # Информация о файле. echo done exit 0

В [списке] цикла for могут быть использованы имена файлов, которые в свою очередь могут содержать символы-шаблоны.

Читайте также:  Apt search linux image

Пример 10-4. Обработка списка файлов в цикле for

#!/bin/bash # list-glob.sh: Создание список файлов в цикле for с использованием # операции подстановки имен файлов ("globbing"). echo for file in * do ls -l "$file" # Список всех файлов в $PWD (текущем каталоге). # Напоминаю, что символу "*" соответствует любое имя файла, # однако, в операциях подстановки имен файлов ("globbing"), # имеются исключения -- имена файлов, начинающиеся с точки. # Если в каталоге нет ни одного файла, соответствующего шаблону, # то за имя файла принимается сам шаблон. # Чтобы избежать этого, используйте ключ nullglob # (shopt -s nullglob). # Спасибо S.C. done echo; echo for file in [jx]* do rm -f $file # Удаление файлов, начинающихся с "j" или "x" в $PWD. echo "Удален файл \"$file\"". done echo exit 0

Пример 10-5. Цикл for без списка аргументов

#!/bin/bash # Попробуйте вызвать этот сценарий с аргументами и без них и посмотреть на результаты. for a do echo -n "$a " done # Список аргументов не задан, поэтому цикл работает с переменной '$@' #+ (список аргументов командной строки, включая пробельные символы). echo exit 0

Пример 10-6. Создание списка аргументов в цикле for с помощью операции подстановки команд

#!/bin/bash # уЩЫЬ for гЯ [гаЩгЫЯЭ], гЯкФСЮЮйЭ г аЯЭЯниР аЯФгдСЮЯзЫЩ ЫЯЭСЮФ. NUMBERS="9 7 3 8 37.53" for number in `echo $NUMBERS` # for number in 9 7 3 8 37.53 do echo -n "$number " done echo exit 0

Более сложный пример использования подстановки команд при создании списка аргументов цикла.

#!/bin/bash # bin-grep.sh: Поиск строк в двоичных файлах. # замена "grep" для бинарных файлов. # Аналогично команде "grep -a" E_BADARGS=65 E_NOFILE=66 if [ $# -ne 2 ] then echo "Порядок использования: `basename $0` string filename" exit $E_BADARGS fi if [ ! -f "$2" ] then echo "Файл \"$2\" не найден." exit $E_NOFILE fi for word in $( strings "$2" | grep "$1" ) # Инструкция "strings" возвращает список строк в двоичных файлах. # Который затем передается по конвейеру команде "grep", для выполнения поиска. do echo $word done # Как указывает S.C., вышепрведенное объявление цикла for может быть упрощено # strings "$2" | grep "$1" | tr -s "$IFS" '[\n*]' # Попробуйте что нибудь подобное: "./bin-grep.sh mem /bin/ls" exit 0

Пример 10-8. Список всех пользователей системы

#!/bin/bash # userlist.sh PASSWORD_FILE=/etc/passwd n=1 # Число пользователей for name in $(awk 'BEGIN' < "$PASSWORD_FILE" ) # Разделитель полей = : ^^^^^^ # Вывод первого поля ^^^^^^^^ # Данные берутся из файла паролей ^^^^^^^^^^^^^^^^^ do echo "Пользователь #$n = $name" let "n += 1" done # Пользователь #1 = root # Пользователь #2 = bin # Пользователь #3 = daemon # . # Пользователь #30 = bozo exit 0

И заключительный пример использования подстановки команд при создании [списка].

Пример 10-9. Проверка авторства всех бинарных файлов в текущем каталоге

#!/bin/bash # findstring.sh: # Поиск заданной строки в двоичном файле. directory=/usr/local/bin/ fstring="Free Software Foundation" # Поиск файлов от FSF. for file in $( find $directory -type f -name '*' | sort ) do strings -f $file | grep "$fstring" | sed -e "s%$directory%%" # Команде "sed" передается выражение (ключ -e), #+ для того, чтобы изменить обычный разделитель "/" строки поиска и строки замены #+ поскольку "/" - один из отфильтровываемых символов. # Использование такого символа порождает сообщение об ошибке (попробуйте). done exit 0 # Упражнение: # --------------- # Измените сценарий таким образом, чтобы он брал #+ $directory и $fstring из командной строки.

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

Читайте также:  Head tail команда линуксе

Пример 10-10. Список символических ссылок в каталоге

#!/bin/bash # symlinks.sh: Список символических ссылок в каталоге. directory=$ # По-умолчанию в текущем каталоге, # Блок кода, который выполняет аналогичные действия. # ---------------------------------------------------------- # ARGS=1 # Ожидается один аргумент командной строки. # # if [ $# -ne "$ARGS" ] # Если каталог поиска не задан. # then # directory=`pwd` # текущий каталог # else # directory=$1 # fi # ---------------------------------------------------------- echo "символические ссылки в каталоге \"$directory\"" for file in "$( find $directory -type l )" # -type l = символические ссылки do echo "$file" done | sort # В противном случае получится неотсортированный список. # Как отмечает Dominik 'Aeneas' Schnitzer, #+ в случае отсутствия кавычек для $( find $directory -type l ) #+ сценарий "подавится" именами файлов, содержащими пробелы. exit 0

Вывод цикла может быть перенаправлен со stdout в файл, ниже приводится немного модифицированный вариант предыдущего примера, демонстрирующий эту возможность.

Пример 10-11. Список символических ссылок в каталоге, сохраняемый в файле

#!/bin/bash # symlinks.sh: Список символических ссылок в каталоге. OUTFILE=symlinks.list # файл со списком directory=$ # По-умолчанию -- текущий каталог, echo "символические ссылки в каталоге \"$directory\"" > "$OUTFILE" echo "---------------------------" >> "$OUTFILE" for file in "$( find $directory -type l )" # -type l = символические ссылки do echo "$file" done | sort >> "$OUTFILE" # перенаправление вывода # ^^^^^^^^^^^^^ в файл. exit 0

Оператор цикла for имеет и альтернативный синтаксис записи -- очень похожий на синтаксис оператора for в языке C. Для этого используются двойные круглые скобки.

Пример 10-12. C-подобный синтаксис оператора цикла for

#!/bin/bash # Два вапианта оформления цикла. echo # Стандартный синтаксис. for a in 1 2 3 4 5 6 7 8 9 10 do echo -n "$a " done echo; echo # +==========================================+ # А теперь C-подобный синтаксис. LIMIT=10 for ((a=1; a 

А сейчас пример сценария, который может найти "реальное" применение.

Пример 10-13. Работа с командой efax в пакетном режиме

#!/bin/bash EXPECTED_ARGS=2 E_BADARGS=65 if [ $# -ne $EXPECTED_ARGS ] # Проверка наличия аргументов командной строки. then echo "Порядок использования: `basename $0` phone# text-file" exit $E_BADARGS fi if [ ! -f "$2" ] then echo "Файл $2 не является текстовым файлом" exit $E_BADARGS fi fax make $2 # Создать fax-файлы из текстовых файлов. for file in $(ls $2.0*) # Все файлы, получившиеся в результате преобразования. # Используется шаблонный символ в списке. do fil="$fil $file" done efax -d /dev/ttyS3 -o1 -t "T$1" $fil # отправить. # Как указывает S.C., в цикл for может быть вставлена сама команда отправки в виде: # efax -d /dev/ttyS3 -o1 -t "T$1" $2.0* # но это не так поучительно [;-)]. exit 0

Оператор while проверяет условие перед началом каждой итерации и если условие истинно (если код возврата равен 0 ), то управление передается в тело цикла. В отличие от циклов for, циклы while используются в тех случаях, когда количество итераций заранее не известно.

Как и в случае с циклами for/in , при размещении ключевого слова do в одной строке с объявлением цикла, необходимо вставлять символ ";" перед do.

Пример 10-14. Простой цикл while

#!/bin/bash var0=0 LIMIT=10 while [ "$var0" -lt "$LIMIT" ] do echo -n "$var0 " # -n подавляет перевод строки. var0=`expr $var0 + 1` # допускается var0=$(($var0+1)). done echo exit 0

Пример 10-15. Другой пример цикла while

#!/bin/bash echo while [ "$var1" != "end" ] # возможна замена на while test "$var1" != "end" do echo "Введите значение переменной #1 (end - выход) " read var1 # Конструкция 'read $var1' недопустима (почему?). echo "переменная #1 = $var1" # кавычки обязательны, потому что имеется символ "#". # Если введено слово 'end', то оно тоже выводится на экран. # потому, что проверка переменной выполняется в начале итерации (перед вводом). echo done exit 0

Оператор while может иметь несколько условий. Но только последнее из них определяет возможность продолжения цикла. В этом случае синтаксис оператора цикла должен быть несколько иным.

Пример 10-16. Цикл while с несколькими условиями

#!/bin/bash var1=unset previous=$var1 while echo "предыдущее значение = $previous" echo previous=$var1 # запомнить предыдущее значение [ "$var1" != end ] # В операторе "while" присутствуют 4 условия, но только последнее управляет циклом. # *последнее* условие - единственное, которое вычисляется. do echo "Введите значение переменной #1 (end - выход) " read var1 echo "текущее значение = $var1" done # попробуйте самостоятельно разобраться в сценарии works. exit 0

Пример 10-17. C-подобный синтаксис оформления цикла while

#!/bin/bash # wh-loopc.sh: Цикл перебора от 1 до 10. LIMIT=10 a=1 while [ "$a" -le $LIMIT ] do echo -n "$a " let "a+=1" done # Пока ничего особенного. echo; echo # +=================================================================+ # А теперь оформим в стиле языка C. ((a = 1)) # a=1 # Двойные скобки допускают наличие лишних пробелов в выражениях. while (( a 

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

Обратите внимание: оператор until проверяет условие завершения цикла ПЕРЕД очередной итерацией, а не после, как это принято в некоторых языках программирования.

Как и в случае с циклами for/in , при размещении ключевого слова do в одной строке с объявлением цикла, необходимо вставлять символ ";" перед do.

Пример 10-18. Цикл until

#!/bin/bash until [ "$var1" = end ] # Проверка условия производится в начале итерации. do echo "Введите значение переменной #1 " echo "(end - выход)" read var1 echo "значение переменной #1 = $var1" done exit 0

PostgresPro

Inferno Solutions

Источник

Оцените статью
Adblock
detector