For цикл в bash

Управляющие конструкции в скриптах

Создание bash скрипта было бы не настолько полезным без возможности анализировать определенные факторы, и выполнять в ответ на них нужные действия. Это довольно-таки сложная тема, но она очень важна для того, чтобы создать bash скрипт.

В Bash для проверки условий есть команда Синтаксис ее такой:

if команда_условие thenкомандаelse командаfi

Эта команда проверяет код завершения команды условия, и если 0 (успех) то выполняет команду или несколько команд после слова then, если код завершения 1 выполняется блок else, fi означает завершение блока команд.

Но поскольку нам чаще всего нас интересует не код возврата команды, а сравнение строк и чисел, то была введена команда [[, которая позволяет выполнять различные сравнения и выдавать код возврата зависящий от результата сравнения. Ее синтаксис:

]

Для сравнения используются уже привычные нам операторы <,>,=,!= и т д. Если выражение верно, команда вернет 0, если нет — 1. Вы можете немного протестировать ее поведение в терминале. Код возврата последней команды хранится в переменной $?:

Теперь объединением все это и получим скрипт с условным выражением:

Конечно, у этой конструкции более мощные возможности, но это слишком сложно чтобы рассматривать их в этой статье. Возможно, я напишу об этом потом. А пока перейдем к циклам.

expr

expr похож на let за исключением того, что вместо сохранения результата в переменную expr по умолчанию печатает ответ.

Но никто не запрещает сохранять результат expr в переменные с помощью command substitution: x = $(expr 2 &plus; 2)

В отличие от let не нужно заключать выражения с пробелами в кавычки

Нужно ставить пробелы вокруг операторов.

Рассмотрим простой пример:

expr_example.sh

Разберём этот пример пошагово:

Строка 4 — Это базовый синтаксис

Обратите внимание на пробелы и на отсутствие кавычек.

Строка 6 — Если заключить выражение в кавычки его в таком виде и выведет в терминал.

Строка 8 — Если не поставить пробелы выражение будет выведено в терминал без вычисления.

Строка 10 — Некоторые символы нужно экранировать.

Строка 12 — Это деление по модулю. Результатом будет остаток от целочисленного деления двух чисел.

Строка 14 — Пример выполнения command substitution чтобы сохранить результат в переменную a

./expr_example.sh 12

9

5 &plus; 4

5&plus;4

60

1

7

Проверки файлов

Kоманды позволяют проверять различные условия, касающиеся файлов

-d file         # Проверяет, существует ли файл, и является ли он директорией.
-e file         # Проверяет, существует ли файл.
-f file         # Проверяет, существует ли файл, и является ли он файлом.
-r file         # Проверяет, существует ли файл, и доступен ли он для чтения.
-s file         # Проверяет, существует ли файл, и не является ли он пустым.
-w file         # Проверяет, существует ли файл, и доступен ли он для записи.
-x file         # Проверяет, существует ли файл, и является ли он исполняемым.
file1 -nt file2 # Проверяет, новее ли file1, чем file2.
file1 -ot file2 # Проверяет, старше ли file1, чем file2.
-O file         # Проверяет, существует ли файл, и является ли его владельцем текущий пользователь.
-G file         # Проверяет, существует ли файл, и соответствует ли его идентификатор группы идентификатору группы текущего пользователя.

#!/bin/bash

mydir=/home/likegeeks

if                     # если файл сущетсвует и он является директорией
then
echo "The $mydir directory exists"  # выводим сообщение
cd $mydir                          # переходим в него 
ls                                  # отображаем содержимое
else                                # ИНАЧЕ
echo "The $mydir directory does not exist"
fi

Использование условий и циклов

  • if… then… else — используется для выполнения кода, если определенное условие выполняется
  • for — используется для выполнения команд для диапазона значений
  • while — используется для выполнения кода, если выполняется определенное условие
  • before — используется для выполнения кода, пока не выполнено определенное условие
  • case — используется для оценки ограниченного количества конкретных значений

if then elsetestif if… then… fi

else if elsetestЛистинг 4 if then else

|| и &&

if… then||&&||&&Рассмотрим эти две строки:

$1ping pingif &&||if… then… else&& ||Упражнение if… then… else

  1. Запустите редактор и создайте скрипт с именем filechk.
  2. Скопируйте содержимое из листинга 4 в этот скрипт.
  3. Запустите с ним пару тестов, такие как ./filechk /etc/hosts, ./filechck /usr, ./filechk non-existing-file.

Операторы

Пайпы | — передает результат выполненной инструкции следующему пайпу

# command1 | command2 | command3  
ls -l | grep .md$ | less

Точка с запятой ; — выполняет команды последовательно

# command2 will be executed after command1
command1 ; command2

Амперсанд & — оболочка выполняет команду асинхронно в подоболочке. Другими словами, эта команда будет выполняться в фоновом режиме

Двойной амперсанд (И) && — вторая команды будет выполнена только в случае УСПЕШНОГО заверения первой команды

# command2 will be executed if, and only if, command1 finishes successfully (returns 0 exit status)
command1 && command2

Двойной пайп (ИЛИ) — вторая команды будет выполнена только в случае НЕУДАЧНОГО заверения первой команды

# command2 will be executed if, and only if, command1 finishes unsuccessfully (returns code of error)
command1 || command2

Тестовые — Эти выражения помогают нам указать результаты условного выражения. Используются обычно в блоках if

# Single-line
if ]; then echo "true"; fi

# Multi-line
if ]; then
  echo "true"
fi

# Single-line
if ]; then echo "true"; else echo "false"; fi

# Multi-line
if ]; then
  echo "true"
else
  echo "false"
fi

Общие слова и замечания

Большинство продемонстрированных клавиш стандартны для «командной строки Linux», но часть из этих комбинаций специфичны для bash (поэтому и пометил это в заголовке). На текущий момент BASH – наиболее распространенный командный интерпретатор, используемый по умолчанию в большинстве Linux-дистрибутивов. В других командных интерпретаторах или, проще говоря, shell’ах (рекомендую попробовать zsh и fish) могут быть небольшие отличия в работе. Также часть комбинаций прописана в «настройках по умолчанию» (например, в файле /etc/inputrc или в /etc/bashrc), которые тоже могут различаться в разных дистрибутивах. И бывает, что некоторые клавиши могут быть настроены и перехватываться графической оболочкой, в которой запущен командный интерпретатор.

Часть демонстрируемых клавиш относятся к «настройкам терминала». А часть – клавиши из командного интерпретатора BASH, и их можно посмотреть, почитав мануал по bash’у (огромный текст – пользуйтесь поиском):

^^^ На приведенном фрагменте из мануала: Запись «(C-r)» означает , а «M->» означает .

Для демонстраций нажатых клавиш использую утилиту «screenkey».

При этом стоит упомянуть, что по умолчанию bash использует emacs-режим редактирования командной строки и поэтому многие комбинации клавиш пришли из редактора emacs. Для знающих редактор vi, могу порекомендовать переключить (добавив «set -o vi» в ~/.bashrc) bash в vi-режим редактирования и пользоваться привычными комбинациями из vi.

Автодополнение

Tab – автодополнение (в контексте)

Во многих командных интерпретаторах (и в bash в том числе) используется такая возможность, как автодополнение. Как минимум нужно знать, что по нажатию клавиши дописывается название команды. В bash по умолчанию обычно настроено так, что если имеется только один вариант дополнения, то он дописывается по нажатию (также можно использовать и ). Когда вариантов дополнения много, то по первому нажатию дописывается только общая часть (если она есть). А по второму нажатию отображается список всех доступных вариантов. Дальше можно набрать еще символов – уточнить, какое из дополнений нужно, и снова нажать . То же самое с другими дополнениями: имен файлов, имен переменных.

^^^ Здесь, например, смотрю (нажав дважды ), что есть несколько команд, начинающихся с «if», добавив «c» и нажав , получаю набранной команду «ifconfig».

^^^ В этом примере дополняю аргументы команды (здесь имена файлов). Также видно, что в случае, когда вариантов много и все не умещаются в окне терминала, их список отображается утилитой для постраничного просмотра (также при очень большом списке вариантов выдается запрос вида «Display all 125 possibilities? (y or n)» или, как в этом примере, при малом количестве — «—More—».

Дополнения имен пользователей, переменных

Часто, когда дописываются аргументы команд по , дописываются имена файлов. Но стоит также отметить, что, в зависимости от контекста, по дописываются и имена переменных (аргументы, начинающиеся с символа «$»), имена пользователей (аргументы, начинающиеся с символа «~»),…

^^^ Здесь, чтобы набрать «$HISTFILESIZE», вместо 13 символов набрал 8 символов ( ). Помимо того, что так быстрее, это еще и позволяет допускать меньше ошибок при наборе команд, так как не просто печатаю текст, а выбираю из списка установленных переменных.

^^^ Здесь дописываю имена пользователей (фактически пишу адрес домашней директории).

Также bash может дополнять не потому, что набранный текст начинается с определенного символа, а по определенным комбинациям клавиш.

Список того, что может дополнять bash, можно посмотреть командой:

Так, например, видно, что:

  • – покажет список имен пользователей, начинающихся с набранных символов, а дополнить комбинацией ;

  • – список имен машин (согласно /etc/hosts), начинающихся с набранных символов, а дополнить – ;

  • – список имен переменных, заданных в этой сессии (можно их также посмотреть командой set), а дополнить – ;

  • – список команд (согласно доступных: $PATH, alias, функций, встроенных команд), а дополнить – ;

  • – список имен файлов, а дополнить – .

Alt-* – вставить дополнения, Ctrl-x * – развернуть шаблон

(точнее, ) или, что, то же самое, (точнее, , , ), вставит все варианты дополнения в командную строку. Аналогично можно развернуть список файлов, переменных, имен пользователей.

В примерах ниже разворачиваю список файлов:

Вариант с :

Вариант с :

– развернет уже написанный в командной строке шаблон, как в примере ниже:

Переменные

  • Используйте ключевое слово read в скрипте, чтобы запросить данные у пользователя, запускающего скрипт.
  • Используйте подстановку команд, чтобы использовать результат команды и назначить его переменной. Например, команда date +%d-%m-%y показывает текущую дату в формате день-месяц-год. Чтобы сделать это в сценарии, вы можете использовать TODAY=$(date +%d-%m-%y). Для подстановки команд вам просто нужно поместить команду, результат которой вы хотите использовать, между скобками.

Листинг 3.read

if… then… else… fi $1test test if …-z $1 — на самом деле тремя (прим. переводчика)-z test$1 if $1then test then testthen echoreadread read TEXT elseelse $1fiechoВы можете попрактиковаться на этом примере при работе с вводом.

  1. Откройте редактор и создайте файл с именем text. Введите содержимое кода из листинга 3 в этот файл.
  2. Запишите файл на диск и выполните chmod +x text, чтобы сделать его исполняемым.
  3. Запустите скрипт, выполнив ./text и без дополнительных аргументов. Вы увидите, что он запрашивает ввод.
  4. Запустите скрипт, используя «hello» в качестве аргумента (./text hello). Результат отобразит «you have entered the text hello» в STDOUT.

Циклы

Как и любой полноценный язык программирования, bash поддерживает циклы. Цикл for и цикл while. Циклы нужны, чтобы выполнять какой-то код заданное число раз. Например, при парсинге CSV перебирать построчно и каждую строку рассматривать отдельно.

Цикл for

Вот пример структуры цикла for:

Простой реальный пример:

Вывод:

Программа просто перебирает все имена, разделенные пробелом, и выводит их с помощью echo.

Попробуем немного усложнить пример:

Создадим файл с именами touch names и запишем в него список имен для приветствия:

Вывод:

Обратите внимание на ^C. Это символ прерывания выполнения программы

В нашем случае мы вызвали программу без аргумента, и она вошла в вечный цикл. Можно сказать, зависла. Пришлось завершить ее принудительно. Не забывайте делать проверки входных данных в реальных программах.  Как это делать, можете посмотреть в главах if-else и switch case, например.  

В нашей программе есть небольшой баг. Модифицируем файл имен:

Запустим программу, получим вывод:

Как говорится, «Кто все эти люди?». Так получается, потому что у нас не задана переменная окружения IFS (Internal Field Separator), указывающая на разделители полей. Наш цикл использует пробелы и переносы строки как разделители. В начале скрипта (после #!/bin/bash) укажите использовать перенос строки как разделитель полей: IFS=$’\n’. 

В итоге мы получим возможность работать со строками целиком. Это пригодится для парсинга CSV.

Обычно цикл for используется со счетчиком. В C-like стиле. Что-то вроде for (i=0;i<10;i++){}. В bash тоже так можно. 

Цикл while

Схема организации цикла while:

Простой способ сделать бесконечную петлю (бесконечный цикл):

Это может пригодится, например, когда вам нужно вызывать что-то чаще, чем позволяет cron (например, раз в минуту). Или когда вам просто надо проверять какое-то значение постоянно. Областей применения у бесконечных циклов много.

Здесь используются те же самые выражения, что и в if:

Вывод:

Из цикла можно выйти с помощью команды break (работает также и для for):

Вывод:

Прочитать файл построчно

Одним из наиболее распространенных использований в петли , чтобы прочитать файл, поток данных или переменной построчно.

Вот пример, который считывает файл построчно и печатает каждую строку:

Вместо того , чтобы контролировать цикл с условием, что мы используем перенаправления ввода ( ) , чтобы передать файл на команды, которая контролирует цикл. В цикл будет выполняться до тех пор , последняя строка не читается.

При чтении файла построчно всегда используйте с опцией чтобы обратная косая черта не использовалась как escape-символ.

По умолчанию команда обрезает начальные / конечные пробельные символы (пробелы и табуляции). Используйте параметр перед чтобы предотвратить такое поведение:

Синтаксис оператора if (краткое объяснение)

Основной синтаксис оператора if … then выглядит следующим образом:

if <condition>; then
<commands>
fi

Условие, в зависимости от его типа, окружено определенным
скобки, например. []. Вы можете прочитать о различных типах дальше
в учебнике. Вы можете добавить команды, которые будут выполняться, когда условие ложно, с помощью ключевого слова else и использовать ключевое слово elif (elseif) для выполнения команд с другим условием, если основное условие ложно. Ключевое слово else всегда стоит последним. Пример:

if ; then
        content=$(cat somefile)
elif ; then
        echo "The file 'somefile' exists but is not readable to the script."
else
        echo "The file 'somefile' does not exist."
fi

Краткое объяснение примера: сначала мы проверяем, является ли файл somefile читаемым («if »). Если так, мы читаем это в переменную. Если нет, мы проверяем, существует ли он на самом деле («elif »). Если это правда, мы сообщаем, что он существует, но не читается (если бы это было так, мы бы прочитали содержимое). Если файл не существует, мы также сообщаем об этом. Условие в elif выполняется только в том случае, если условие в if было ложным. Команды, принадлежащие else, выполняются, только если оба условия ложны.

Основы скриптов

Скрипт или как его еще называют — сценарий, это последовательность команд, которые по очереди считывает и выполняет программа-интерпретатор, в нашем случае это программа командной строки — bash.

Скрипт — это обычный текстовый файл, в котором перечислены обычные команды, которые мы привыкли вводить вручную, а также указанна программа, которая будет их выполнять. Загрузчик, который будет выполнять скрипт не умеет работать с переменными окружения, поэтому ему нужно передать точный путь к программе, которую нужно запустить. А дальше он уже передаст ваш скрипт этой программе и начнется выполнение.

Простейший пример скрипта для командной оболочки Bash:

Утилита echo выводит строку, переданную ей в параметре на экран. Первая строка особая, она задает программу, которая будет выполнять команды. Вообще говоря, мы можем создать скрипт на любом другом языке программирования и указать нужный интерпретатор, например, на python:

Или на PHP:

В первом случае мы прямо указали на программу, которая будет выполнять команды, в двух следующих мы не знаем точный адрес программы, поэтому просим утилиту env найти ее по имени и запустить. Такой подход используется во многих скриптах. Но это еще не все. В системе Linux, чтобы система могла выполнить скрипт, нужно установить на файл с ним флаг исполняемый.

Этот флаг ничего не меняет в самом файле, только говорит системе, что это не просто текстовый файл, а программа и ее нужно выполнять, открыть файл, узнать интерпретатор и выполнить. Если интерпретатор не указан, будет по умолчанию использоваться интерпретатор пользователя. Но поскольку не все используют bash, нужно указывать это явно.

Чтобы сделать файл исполняемым в linux выполните:

Теперь выполняем нашу небольшую первую программу:

Все работает. Вы уже знаете как написать маленький скрипт, скажем для обновления. Как видите, скрипты содержат те же команды, что и выполняются в терминале, их писать очень просто. Но теперь мы немного усложним задачу. Поскольку скрипт, это программа, ему нужно самому принимать некоторые решения, хранить результаты выполнения команд и выполнять циклы. Все это позволяет делать оболочка Bash. Правда, тут все намного сложнее. Начнем с простого.

Параметры скриптов

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

Для того, чтобы получить значение первого параметра, необходимо в скрипте указать , второго — , и т.д. Существует также ряд других переменных, значения которых можно использовать в скрипте: – имя скрипта – количество переданных параметров – PID(идентификатор) процесса, выполняющего скрипт – код завершения предыдущей команды

Создадим файл script1.sh следующего содержания:

Выдадим права на выполнение и выполним скрипт с параметрами:

Мы передали 2 параметра, указывающие город и страну, и использовали их в скрипте, чтобы сформировать строку, выводимую командой printf. Также для вывода в строке Hello использовали имя пользователя из переменной USER.

Для того, чтобы передать значения параметров, состоящие из нескольких слов (содержащие пробелы), нужно заключить их в кавычки:

При этом нужно доработать скрипт, чтобы в команду printf параметры также передавались в кавычках:

Из приведенных примеров видно, что при обращении к переменной для получения её значения используется символ $. Для того, чтобы сохранить значение переменной просто указывается её имя:

Что такое Bash?

Как я уже говорил, Bash — это интерпретатор команд. По сути, это обычная программа, которая запускается при старте сеанса оболочки. Мы могли бы запускать не Bash, а скажем, интерпретатор python или ruby, и тогда нам пришлось бы выполнять методы этих языков вместо команд Bash для администрирования системы.

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

Массивы Bash

Массивы оболочки Bash работают почти так же, как и в других языках программирования. Перед тем как вы сможете использовать массив, его нужно объявить. Это можно сделать несколькими способами, первый из них — это использование команды оболочки declare:

declare -a имя_массива

Но необязательно делать именно так, вы можете сразу начать задавать элементы массива по нужным номерам:

имя_массива[XX = значение

Здесь XX обозначает индекс массива. Еще один удобный способ создавать массивы строк Bash — это просто перечислить все элементы в круглых скобках:

имя_массива=( элемент_1, элемент_2 элемент_3 … )

Или вы можете сразу задать индекс массива для каждого из элементов:

имя_массива=( =значение =значение . . . )

Также можно прочитать значения для массива из клавиатуры или другого источника ввода:

read -a имя_массива

При вводе элементов массива они должны быть разделены символом пробела

Для получения значений элементов массива используйте синтаксис фигурных скобок, обратите внимание, что нумерация элементов массива, как и в большинстве языков начинается с нуля:. ${имя_массиваXX]}

${имя_массиваXX]}

Это все основные моменты, которые будут вам полезны при использовании массивов, теперь нам осталось рассмотреть основные примеры, чтобы вам было более понятно как все это работает.

Файловая система

Просмотр содержимого папки

pwd                     # выводит текущи путь (сокращение от PRINT WORK DIRECTORY)
ls                      # показать содержимое папки
ls -l                   # отображает расширенную информацию о файлах и папках
ls -a                   # то же, но показывать и скрытые файлы и папки
ls -a -1                # то же, но в один столбец
ls -hF -1 --sort=extension # показать содержимое папки «красиво, в один столбец»
ls build/css            # показать содержимое папки ТЕКУЩАЯ_ПАПКА/build/css
ls /d/projects          # показать содержимое папки D:/projects

Перемещение по файловой системе

Пользователь всегда находится в какой-то папке, она (или полный путь) всегда показана до области ввода команд.

cd projects             # переход в папку projects, которая есть текущей папке
cd /d/projects          # windows: переход в папку projects, расположенную по адресу D:/projects 
cd /c/Program\ Files    # windows: переход в C/:Program Files 
cd .                    # текущая директория
cd ..                   # переход к родительской папке 
cd ~                    # домашняя директория
cd -                    # переход к последней рабочей папке

Чтобы не набирать имя папки целиком, наберите первые пару символов и нажмите Tab — произойдет автодополнение (если нет двух папок, начинающихся с введенных символов, иначе будут показаны сами эти папки). Справедливо для любой команды.

Создание папок и файлов

mkdir project                        # создать папку с именем «project»
mkdir project project/css project/js # создать несколько папок
mkdir -p project/{css,js}            # то же, что выше

touch index.html                     # создать файл
touch index.html css/style.css js/script.js # создать файлы (папки css/ и js/ должны уже существовать)

Копирование файлов

cp index.html catalog.html # копирование файла index.html в тот же каталог с переименованием в catalog.html
cp index.html old/         # копирование файла index.html в папку old/ (все произойдет в текущей папке)
cp temp/ temp2/ -r         # дублирование каталога

Переименование или перемещение файлов

mv index.html old              # перемещение файла в папку
mv index.html old/new_name.txt # перемещение файла в папку с переименованием файла
mv order.txt orderNew.txt      # переименовать файл

Сравнение чисел

В скриптах можно сравнивать числовые значения. Ниже приведён список соответствующих команд.

Сравнения пишем в обязательно пробелы в скобках

# eq - equal  
# ge - greater equal   
# gt - greater than     
# le - less equal  
# lt - less than  
# ne - not equal  

n1 -eq n2 # Возвращает истинное значение, если n1 равно n2.
n1 -ge n2 # Возвращает истинное значение, если n1 больше или равно n2.
n1 -gt n2 # Возвращает истинное значение, если n1 больше n2.
n1 -le n2 # Возвращает истинное значение, если n1 меньше или равно n2.
n1 -lt n2 # Возвращает истинное значение, если n1 меньше n2.
n1 -ne n2 # Возвращает истинное значение, если n1 не равно n2.

val1=6
if 
then
echo "The test value $val1 is greater than 5"
else
echo "The test value $val1 is not greater than 5"
fi

Управляющая конструкция if-then-else

Для того, чтобы программа смогла сообщить и о результатах успешного поиска, и о неудаче, воспользуемся конструкцией . Вот как она устроена:

if команда
then
команды
else
команды
fi

Если первая команда возвратит ноль, что означает её успешное выполнение, условие окажется истинным и выполнение не пойдёт по ветке else. В противном случае, если будет возвращено что-то, отличающееся от нуля, что будет означать неудачу, или ложный результат, будут выполнены команды, расположенные после else.

#!/bin/bash

user=anotherUser
if grep $user /etc/passwd
then
echo "The user $user Exists"
else
echo "The user $user doesn’t exist"
fi
Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Ваша ОС
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: