- for цикл в Bash
- Стандартный for цикл в Bash
- Оберните струны
- Цикл по диапазону чисел
- Перебирать элементы массива
- Цикл for в Bash в стиле C
- Операторы break и continue
- Оператор break
- Оператор continue
- Примеров циклов for в Bash
- Переименование файлов с пробелами в имени файла
- Изменение расширения файла
- Выводы
- Bash цикл For
- Bash For Loop
- В этом уроке мы рассмотрим основы циклов for в Bash. Мы также покажем вам , как использовать break и continue, чтобы изменить поток цикла.
- Стандартный цикл for
- Зацикливание строк
- Цикл по диапазону номеров
- Цикл на элементах массива
- Синтаксис цикла в стиле C
- break и continue заявления
- break
- continue
- Примеры цикла for Bash
- Переименование файлов с пробелами в имени файла
- Изменение расширения файла
- Вывод
- Bash в примерах. Часть вторая.
- Еще больше основ программирования в bash
- Обработка аргументов
- Управляющие конструкции bash
- Оператор условного выбора «if»
- Тонкости при сравнении строк
- Конструкция создания циклов «for»
- Арифметика в shell
- Циклические конструкции с условиями («while» и «until»)
- Экстренный выход из цикла
- Команда–переключатель «case»
- Функции и пространство имен
- Пространство имен
- Подведение итогов
for цикл в Bash
Циклы — одна из фундаментальных концепций языков программирования. Циклы удобны, когда вы хотите запускать серию команд снова и снова, пока не будет достигнуто определенное условие.
В языках сценариев, таких как Bash, циклы полезны для автоматизации повторяющихся задач. В Bash доступны три основные конструкции цикла: for , while и until циклы.
В этом руководстве мы рассмотрим основы циклов for в Bash. Мы также покажем вам, как использовать операторы break и continue чтобы изменить ход цикла.
Стандартный for цикл в Bash
Цикл for выполняет итерацию по списку элементов и выполняет заданный набор команд.
Цикл for Bash имеет следующую форму:
Список может быть серией строк, разделенных пробелами, диапазоном чисел, выводом команды, массивом и т. Д.
Оберните струны
В приведенном ниже примере цикл будет перебирать каждый элемент в списке строк, и переменный element будет установлен на текущий элемент:
Цикл выдаст следующий результат:
Цикл по диапазону чисел
Вы можете использовать выражение последовательности, чтобы указать диапазон чисел или символов, задав начальную и конечную точки диапазона. Выражение последовательности принимает следующую форму:
Вот пример цикла, который перебирает все числа от 0 до 3:
Начиная с Bash 4, также можно указывать приращение при использовании диапазонов. Выражение принимает следующий вид:
Вот пример, показывающий, как увеличить на 5:
Перебирать элементы массива
Вы также можете использовать цикл for для перебора массива элементов.
В приведенном ниже примере мы определяем массив с именем BOOKS и перебираем каждый элемент массива.
Цикл for в Bash в стиле C
Синтаксис цикла for стиле C имеет следующий вид:
Часть INITIALIZATION выполняется только один раз при запуске цикла. Затем оценивается TEST . Если это ложь, цикл прекращается. Если TEST истинен, команды внутри цикла for выполняются, а часть STEP обновляется.
В следующем примере кода цикл начинается с инициализации i = 0 и перед каждой итерацией проверяется, является ли i ≤ 10 . Если true, он печатает текущее значение i и [увеличивает переменную] i на 1 ( i++ ), в противном случае цикл завершается.
Цикл повторится 1001 раз и выдаст следующий результат:
Операторы break и continue
Операторы break и continue могут использоваться для управления выполнением цикла for.
Оператор break
Оператор break завершает текущий цикл и передает управление программой оператору, следующему за завершенным оператором. Обычно он используется для завершения цикла при выполнении определенного условия.
В следующем примере мы используем оператор if для прекращения выполнения цикла, когда текущий повторяемый элемент становится равным «Lithium».
Оператор continue
Оператор continue завершает текущую итерацию цикла и передает управление программой следующей итерации цикла.
В следующем примере мы перебираем диапазон чисел. Когда текущий повторяемый элемент равен ‘2’, оператор continue заставит выполнение вернуться к началу цикла и продолжить следующую итерацию:
Примеров циклов for в Bash
Переименование файлов с пробелами в имени файла
В следующем примере показано, как переименовать все файлы в текущем каталоге с пробелом в его именах, заменив пробел на подчеркивание:
Давайте разберем код построчно:
- Первая строка создает цикл for и выполняет итерацию по списку всех файлов с пробелом в имени. Выражение * * создает список.
- Вторая строка применяется к каждому элементу списка и перемещает файл в новый, заменяя пробел знаком подчеркивания ( _ ). Часть $
использует расширение параметра оболочки для замены шаблона в параметре строкой. - done указывает конец сегмента цикла.
Изменение расширения файла
В следующем примере показано, как использовать цикл for в Bash for переименования всех файлов, оканчивающихся на .jpeg, в текущем каталоге путем замены расширения файла с .jpeg на .jpg.
Давайте проанализируем код построчно:
- Первая строка создает цикл for и выполняет итерацию по списку всех файлов, заканчивающихся на ‘.jpeg’.
- Вторая строка применяется к каждому элементу списка и перемещает файл в новый, заменяя «.jpeg» на «.jpg». $
чтобы удалить часть ‘.jpeg’ из имени файла, используя расширение параметра оболочки - done указывает конец сегмента цикла.
Выводы
Цикл for Bash используется для повторного выполнения заданного набора команд определенное количество раз.
Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять комментарии.
Источник
Bash цикл For
Bash For Loop
В этом уроке мы рассмотрим основы циклов for в Bash. Мы также покажем вам , как использовать break и continue, чтобы изменить поток цикла.
Циклы являются одним из фундаментальных понятий языков программирования. Циклы удобны, когда вы хотите запускать серию команд снова и снова, пока не будет достигнуто определенное условие.
В языках сценариев, таких как Bash, циклы полезны для автоматизации повторяющихся задач.
В скриптах Bash есть три базовых конструкции for , while и until .
Стандартный цикл for
for Цикл перебирает список элементов и выполняет данный набор команд.
Цикл Bash for принимает следующую форму:
Список может быть последовательностью строк, разделенных пробелами, диапазоном чисел, выводом команды, массивом и так далее.
Зацикливание строк
В приведенном ниже примере цикл будет перебирать каждый элемент в списке строк, и переменная element будет установлена на текущий элемент:
Цикл выдаст следующий вывод:
Цикл по диапазону номеров
Вы можете использовать выражение последовательности, чтобы указать диапазон чисел или символов, задав начальную и конечную точку диапазона. Выражение последовательности принимает следующую форму:
Вот пример цикла, который перебирает все числа от 0 до 3:
Начиная с Bash 4, также можно указать приращение при использовании диапазонов. Выражение принимает следующую форму:
Вот пример, показывающий, как увеличить на 5:
Цикл на элементах массива
Вы также можете использовать for цикл для перебора массива элементов.
В приведенном ниже примере мы определяем массив с именем BOOKS и выполняем итерацию по каждому элементу массива.
Синтаксис цикла в стиле C
Синтаксис цикла в стиле C for принимает следующую форму:
В следующем примере кода цикл начинается с инициализации i = 0 и перед каждой итерацией проверяет, является ли i ≤ 10 . Если true, он печатает текущее значение i и [увеличивает переменную] i на 1 ( i++ ), иначе цикл завершается.
Цикл повторяется 1001 раз и выдает следующий результат:
break и continue заявления
break и continue могут быть использованы для управления для выполнения цикла.
break
В следующем примере мы используем if инструкцию, чтобы завершить выполнение цикла, когда текущий повторяющийся элемент равен «Lithium».
continue
В следующем примере мы перебираем диапазон чисел. Когда текущий элемент continue с итерацией равен ‘2’, оператор заставит выполнение вернуться к началу цикла и продолжить следующую итерацию:
Примеры цикла for Bash
Переименование файлов с пробелами в имени файла
В следующем примере показано, как переименовать все файлы в текущем каталоге с пробелом в его именах, заменив пробел подчеркиванием:
Давайте разберем код построчно:
- Первая строка создает for цикл и перебирает список всех файлов с пробелом в имени. Выражение *\ * создает список.
- Вторая строка применяется к каждому элементу списка и перемещает файл в новый, заменяя пробел подчеркиванием ( _ ). Часть $
использует расширение параметра оболочки для замены шаблона в параметре на строку. - done указывает на конец сегмента цикла.
Изменение расширения файла
В следующем примере показано, как использовать for цикл Bash для переименования всех файлов, заканчивающихся на .jpeg в текущем каталоге, заменив расширение файла с .jpeg на .jpg.
Давайте проанализируем код построчно:
- Первая строка создает for цикл и просматривает список всех файлов, заканчивающихся на «.jpeg».
- Вторая строка применяется к каждому элементу списка и перемещает файл в новый, заменяя «.jpeg» на «.jpg». $
удалить часть «.jpeg» из имени файла, используя расширение параметра оболочки - done указывает на конец сегмента цикла.
Вывод
Цикл Bash for используется для многократного выполнения заданного набора команд в течение фиксированного числа раз.
Источник
Bash в примерах. Часть вторая.
Еще больше основ программирования в bash
Обработка аргументов
Давайте разберемся как передавать и обрабатывать аргументы скрипта и ознакомимся с основными управляющими конструкциями bash.
В простом скрипте из предыдущей статьи мы использовали переменную «$1«, которая содержит первый аргумент командной строки при вызове скрипта. Аналогично можно использовать «$2», «$3» и так далее для доступа ко второму, третьему… аргументам командной строки. Вот пример:
#!/bin/bash echo «Имя скрипта — $0» echo «Первый аргумент: $1» echo «Второй аргумент: $<2>» echo «Семнадцатый аргумент: $<17>» echo «Количество аргументов: $#»
Обратите внимание, что в переменной «$0» содержится имя самого скрипта, который запущен из командной строки. А переменная «$#» содержит количество переданных скрипту аргументов. Использование фигурных скобок необязательно только для переменных состоящих из одной цифры (с $0 по $9). Попробуйте позапускать этот скрипт с разным числом аргументов и посмотрите как он работает.
Иногда необходимо сослаться сразу на все аргументы командной строки. Для этого в bash есть специальная переменная «$@«, которая содержит все аргументы переданные скрипту разделенные пробелами. Мы будем использовать эту переменную чуть позже при рассказе о циклах со счетчиком (конструкция «for»).
Управляющие конструкции bash
Если вы раньше программировали на процедурных языках, таких как Си, Паскаль, Перл и тому подобных, вам должны быть знакомы управляющие конструкции вроде «if», «for» и другие. В bash тоже есть все эти конструкции. В следующих разделах пособия я познакомлю вас с ними и покажу чем они отличаются от подобных конструкций из других языков программирования. Если вы раньше не программировали — не волнуйтесь. Материал будет изложен подробно и дополнен примерами, так что даже новичок в программировании сможет разобраться.
Оператор условного выбора «if»
Если вы раньше программировали на языке Си, то должны знать сколько требуется усилий чтобы определить какой из двух файлов был создан первым, например. А все из-за того, что в Си нет встроенных средств для такого рода сравнения. Вместо этого приходится использовать системный вызов stat() для каждого файла и затем сравнивать результат вручную. Но в bash есть встроенный механизм сравнения файлов, Поэтому узнать «доступен ли для чтения файл /tmp/myfile» настолько же просто как и узнать «превосходит ли значение переменной ‘myvar’ 4».
Привожу список наиболее часто употребляемых в bash операторов сравнения
Файлы -a file истинно если файл существует. -d file истинно если файл существует и является директорией. -f file истинно если файл существует и является обычным файлом. -r file истинно если файл существует и доступен для чтения. -s file истинно если файл существует и его размер больше 0. -w file истинно если файл существует и доступен для записи. -x file истинно если файл существует и является исполняемым. file1 -nt file2 истинно если файл file1 новее чем file2 или file1 (в соответствии со временем последнего изменения) существует, а file2 нет. file1 -ot file2 истинно если файл file1 старше чем file2 или file2 существует, а file1 нет. file1 -ef file2 истинно если оба файла ссылаются на одно и то же устройство или инод. Строки -z string истинно если строка имеет нулевую длину. -n string истинно если длина строки не нулевая. string1 = string2 истинно если строки равны. string1 != string2 истинно если не равны. string1 истинно если строка 1 стоит в алфавитном порядке перед строкой 2. string1 > string2 истинно если строка 1 стоит в алфавитном порядке после строки 2.
В следующих примерах показано как использовать оператор сравнения в конструкции «if»:
if [ -z «$myvar» ] then echo «Переменная ‘myvar’ не определена.» fi
Квадратные скобки вычисляют условное выражение стоящее в них (это синоним встроенной функции bash — test). Возвращаемый результат — 1 или 0 в зависимости от того выполняется условие или нет. в скобках может стоять несколько выражений, связанных логическими операторами «и» или «или«. Подробнее на странице справки help test.
В некоторых случаях одна и та же операция сравнения может быть сделана несколькими разными способами. Обе конструкции из следующего примера функционально идентичны:
if [ «$myvar» -eq 3 ] then echo «myvar равно 3» fi if [ «$myvar» = «3» ] then echo «myvar равно 3» fi
В первой конструкции из предыдущего примера использована операция арифметического сравнения, а во втором — операция сравнения строк.
Тонкости при сравнении строк
В большинстве случаев, когда вы не заключаете строки и строковые переменные в двойные кавычки, это может привести к ошибке. Почему? Да потому что в строке может встретится пробел или символ табуляции, которые bash не сможет правильно обработать. Вот пример некорректного сравнения строк:
if [ $myvar = «foo bar oni» ] then echo «yes» fi
В этом примере, если значение переменной «$myvar» будет равно «foo», код будет работать как и ожидается и не печатать ничего. Но если значение переменной «$myvar» будет равно «foo bar oni», скрипт вызовет следующую ошибку:
[: too many arguments
После подстановки значения переменной, bash пытается произвести следующую операцию сравнения:
[ foo bar oni = «foo bar oni» ]
В этом случае bash не может правильно обработать сравнение строк содержащих пробелы, одна из которых не заключена в двойные кавычки. Интерпретатор думает, что в квадратных скобках слишком много аргументов. После заключения переменной в двойные кавычки, ошибка не возникает и код работает так как мы задумали. Запомните, если вы возьмете в привычку заключать в двойные кавычки все строковые аргументы и переменные, то избежите множества ошибок подобных описанной выше. Вот исправленный кусок кода:
if [ «$myvar» = «foo bar oni» ] then echo «yes» fi
Этот код будет работать корректно и не преподнесет нам больше никаких неприятных сюрпризов.
Конструкция создания циклов «for»
Хорошо, с условными переходами разобрались, пора перейти к циклическим конструкциям. Начнем с управляющей конструкции «for«. Вот стандартный пример:
#!/bin/bash for x in one two three four do echo «number $x» done Результат: number one number two number three number four
Что же именно произошло? Часть «for x» цикла «for» определяет переменную (называемую итератором) «$x», которая последовательно принимает значения «one», «two», «three», и «four» (по одному за один такт цикла). После присвоения каждого нового значения переменной «$x», выполняется тело цикла (код между словами «do» и «done»). В теле цикла мы выводим на печать значение переменной «$x». Заметим, что после слова «in» в конструкции «for» всегда стоит некий список. В данном примере мы указали четыре слова, но этот список может содержать имена файлов или даже шаблон (wildcard). В следующем примере показано как использовать шаблоны при инициализации итератора цикла:
#!/bin/bash for myfile in /etc/r* do if [ -d «$myfile» ] then echo «$myfile (dir)» else echo «$myfile» fi done результат: /etc/rc0.d (dir) /etc/rc1.d (dir) /etc/rc2.d (dir) /etc/rc3.d (dir) /etc/rc4.d (dir) /etc/rc5.d (dir) /etc/rc6.d (dir) /etc/rc.local /etc/rcS.d (dir) /etc/rearj.cfg /etc/reportbug.conf /etc/resolvconf (dir) /etc/resolv.conf /etc/rmt /etc/rpc /etc/rsyslog.conf /etc/rsyslog.d (dir)
Код этого цикла исполнится для каждого файла из /etc/ имя которого начинается с «r». Сначала bash найдет все такие файлы и заменит шаблон строкой /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d … /etc/rsyslog.d перед тем как приступить к выполнению цикла. В теле цикла для каждого файла из списка проверяется является ли этот файл директорией при помощи оператора «-d«. Если файл оказался директорией, рядом с его называнием печатается «(dir)».
В списке инициализации итератора можно использовать несколько шаблонов одновременно и даже переменные окружения:
for x in /etc/r. /var/lo* /home/drobbins/mystuff/* /tmp/$
Bash в этом примере подставляет значение переменной и раскрывает шаблоны. А затем копирует все файлы в заданную директорию.
До этого все примеры содержали шаблоны основанные на абсолютных путях, но можно использовать и относительные:
for x in ../* mystuff/* do echo «$x is a silly file» done
В этом примере bash раскрывает шаблон относительно текущей рабочей директории (не той в которой находится скрипт, а той которую показывает команда «pwd»). Поиграйтесь с этим скриптом, позапускайте его из разных директорий и посмотрите на результат.
Иногда может потребоваться запустить цикл по списку аргументов из командной строки. Вот как это делается:
В этом примере мы использовали переменную «$@» о которой говорили выше.
Арифметика в shell
Перед тем как приступить к разбору следующего вида циклической конструкции, научимся при помощи интерпретатора производить простые арифметические операции. Просто заключите арифметическое выражение в конструкцию «$(( ))» и bash посчитает ее значение. Вот несколько примеров:
$ echo $(( 100 / 3 )) 33 $ myvar=»56″ $ echo $(( $myvar + 12 )) 68 $ echo $(( $myvar — $myvar )) 0 $ myvar=$(( $myvar + 1 )) $ echo $myvar 57
Теперь, когда вы познакомились с вычислением арифметических выражений в shell, пришло время рассказать о циклических конструкциях «while» и «until».
Циклические конструкции с условиями («while» и «until»)
«while»–цикл исполняется пока выражение в квадратных скобках истинно. Он имеет следующий формат:
while [ условие ] do код done
В следующем примере тело цикла исполняется ровно 10 раз:
myvar=0 while [ $myvar -ne 10 ] do echo «$myvar» myvar=$(( $myvar + 1 )) done
После каждого выполнения кода тела цикла переменная «myvar» увеличивается на 1. Когда значение переменной становится равным 10, условие в квадратных скобках не выполняется и цикл прерывается.
«Until»–цикл очень похож на «while»–цикл: он повторяется пока выражение в квадратных скобках ложно. Вот пример «until»–цикла по функциональности идентичного «while»–циклу из предыдущего примера:
myvar=0 until [ $myvar -eq 10 ] do echo $myvar myvar=$(( $myvar + 1 )) done
Экстренный выход из цикла
Для экстренного выхода из «for», «while» или «until» цикла используется команда break. Для выхода из нескольких вложенных циклов — break N, где N — количество вложенных циклов.
name=0 while : do wget http://example.com/gallery/$
В последнем примере: «while :» — бесконечный цикл. Двоеточие — это команда bash которая не делает ничего но всегда завершается успехом. Переменная $? содержит статус с которым завершилась последняя команда (подробнее о специальных переменных смотри man bash). В нашем случае код отличный от 0 обозначает что при скачивании файла произошла ошибка. Как только условие в квадратных скобках выполнено, интерпретатор переходит к исполнению команды стоящей после логического и (&&). Break прерывает выполнение цикла.
Предпоследнюю строку предыдущего примера можно заменить на знакомую нам условную конструкцию «if» (помним, что в bash одно действие можно сделать несколькими разными способами):
то же самое но через условную конструкцию:
if [ $? -ne 0 ] then break fi
Или в одну строку
if [ $? -ne 0 ]; then break; fi
Да, конструкции можно записывать в одну строку, только нужно поставить несколько разделяющих знаков «точка с запятой». Но не стоит привыкать к такой форме записи — это усложняет читаемость кода.
Команда–переключатель «case»
Конструкция условного перехода «case» может оказаться очень полезной. Вот пример ее использования:
case «$
В этом примере сначала происходит обработка строки в переменной «$x» — «$
Функции и пространство имен
В bash вы можете определять свои функции, как и в других языках программирования (C, Pascal…). Эти функции могут принимать аргументы, используя механизм очень похожий на механизм работы с аргументами командной строки. Вот пример определения простой функции:
tarview() < echo -n "Displaying contents of $1 " if [ $<1##*.>= tar ] then echo «(uncompressed tar)» tar tvf $1 elif [ $ <1##*.>= gz ] then echo «(gzip-compressed tar)» tar tzvf $1 elif [ $ <1##*.>= bz2 ] then echo «(bzip2-compressed tar)» cat $1 | bzip2 -d | tar tvf — fi >
Выше мы определили функцию с именем «tarview», которая принимает один аргумент — имя тарбола. Эта функция определяет вид тарбола (без сжатия, сжатый gzip-ом или bzip2) по расширению, затем печатает этот тип и показывает содержимое архива. Если формат определить не удалось, выводится соответствующее сообщение. Вот пример вызова функции:
$ ./tarview.sh shorten.tar.gz Displaying contents of shorten.tar.gz (gzip-compressed tar) drwxr-xr-x ajr/abbot 0 1999-02-27 16:17 shorten-2.3a/ -rw-r—r— ajr/abbot 1143 1997-09-04 04:06 shorten-2.3a/Makefile -rw-r—r— ajr/abbot 1199 1996-02-04 12:24 shorten-2.3a/INSTALL -rw-r—r— ajr/abbot 839 1996-05-29 00:19 shorten-2.3a/LICENSE .
Как вы видите, обращение к аргументам внутри функции происходит по тем же именам как и к аргументам командной строки внутри скрипта. Переменная «$#» содержит количество переданных функции аргументов. Единственное что остается по-прежнему — переменная «$0«. Она содержит название скрипта при вызове функции из скрипта или строку «bash» при вызове функции напрямую из командной строки.
Вызвать функцию из командной строки можно следующим образом: сохраняем код функции в файл (например с названием «/myfunc.txt») а затем даем следующую команду:
или что тоже самое
Эти команды строка за строкой исполняют инструкции написанные в файле в текущей командной оболочке. (Можно так же напечатать код функции строка за строкой в командной строке, но первый способ намного удобнее). После этого можем вызывать нашу функцию прямо из командной строки:
/.bash_profile, тогда вы сможете вызывать ее из командной строки в любое время при следующем логине.
Пространство имен
Часто возникает потребность создать переменную окружения внутри функции. В большинстве компилируемых языков (например Си), когда вы создаете переменную внутри функции, она попадает в отдельное пространство имен этой функции. Например, если вы напишите функцию «my function» на C и внутри этой функции создадите переменную «x», то она никак не повлияет на переменную с тем же именем «x», созданную вне функции «myfunction».
Но в bash все по-другому. В bash, когда вы создаете переменную внутри функции, она попадает в общее пространство имен. Это значит, что она может перезаписать значение глобальной переменной с таким же именем и продолжит свое существование даже после завершения исполнения функции:
Результатом исполнения этого кода будет строка «ne two three three«, показывающая что переменная «myvar», созданная внутри функции перезаписала значение глобальной переменной «myvar» и что последнее значение итератора «x» равное «three» продолжило существование даже после завершения функции.
В этом простом примере ошибку легко заметить и устранить, переименовав переменные внутри функции. Но есть гораздо более правильное решение этой проблемы: при создании переменной можно явно указать что она является локальной при помощи инструкции «local«. Созданная таким способом внутри функции переменная будет отнесена к локальному пространству имен этой функции и не сможет никак повлиять на глобальную переменную с таким же именем. Следующий пример демонстрирует возможность создания локальной переменной:
Результатом выполнения этого кода будет строка «hello» — значение глобальной переменной «myvar» (на которую никак не повлияла локальная переменная «myvar», созданная внутри функции), а локальная переменная «x» перестает существовать после завершения функции.
Единственное условие при котором вы не должны использовать локальные переменные внутри функций — если хотите изменить значение глобальной переменной.
Подведение итогов
Вот и все. Теперь вы имеете представление о программировании в bash и можете писать свои скрипты. За более подробной информацией обращайтесь к справке man bash или к руководству Advanced Bash-Scripting Guide
Источник