Гарольд Родригес - Краткое введение в программирование на Bash
#!/bin/bash
# Эта программа считает от 1 до 10:
for i in 1 2 3 4 5 6 7 8 9 10; do
echo $i
done
Даже если вы пока не понимаете скрипты на Bash, вы сразу же поймете, что делает приведенный выше пример, благодаря комментарию. Комментирование кода — хорошая практика. Со временем вы поймете, что, если вам нужно будет поддерживать ваши скрипты, то при наличии комментированного кода — делать это станет легче.
Переменные
Переменные это просто «контейнеры», которые содержат некоторые значения. Создавать их нужно по многим причинам. Вам нужно будет как-то сохранять вводимые пользователем данные, аргументы или числовые величины. Например:
#!/bin/bash
x=12
echo ”Значение переменной x - $x”
Здесь мы присвоили переменной x значение 12. Строка echo “Значение переменной х - $x”напечатает текущее значение x. При определении переменной не допускается наличие каких-то пробелов между именем переменной и оператором присваивания: «=». Синтаксис следующий:
имя_переменной=ее_значение.
Обращение к переменным выполняется с помощью префикса «$» перед именем переменной. Именно таким образом мы получаем доступ к значению переменной х с помощью команды echo $x.
Есть два типа переменных — локальные и переменные окружения. Переменные окружения устанавливаются системой и имеют специальной назначение. Обычно их значение может быть выведено с помощью команды echo. Например, если ввести:
$ echo $SHELL
/bin/bash
Вы получили имя оболочки, запущенной в данный момент. Переменные среды задаются в файле /etc/profile и в ~/.bash_profile. Команда echo может применяться для проверки текущего значения переменной.
Примечание:задание переменных среды подробно описано в этой статье — «Как задавать переменные среды». В статье также описаны некоторые особенности оболочки Bash.
Если вы все еще возникают проблемы с пониманием того зачем нужно использовать переменные, приведем пример:
#!/bin/bash
echo "Значение х - 12".
echo "У меня есть 12 карандашей".
echo "Он сказал мне, что значение х равно 12".
echo "Мне 12 лет."
echo "Как получилось, что значение х равно 12?"
Хорошо, теперь предположим, что вы решите поменять значение х на 8 вместо 12. Что для этого нужно сделать? Вы должны изменить все строки кода, в которых говорится, что х равно 12. Но погодите… Есть другие строки кода, где упоминается это число, поэтому простую автозамену использовать не получится. Теперь приведем аналогичный пример, только с использованием переменных:
#!/bin/bash
x=12 # задаем переменной х значение 12
echo "Значение х = $х"
echo "У меня есть 12 карандашей"
echo "Он сказал мне, что значение х равно $х"
echo "Мне 12 лет"
echo "Как получилось, что значение х равно $x?"
Здесь мы видим, что $x выводит текущее значение переменной х равное 12. Поэтому теперь, если вы хотите задать новое значение х равное 8, то все что вам нужно сделать, это изменить одну строчку с х=12 на х=8, и в выводе все строки с упоминанием x также изменяться. Поэтому вам не нужно руками модифицировать остальные строки. Как вы увидите позже, переменные имеют и другие способы применения.
Управляющие операторы
Управляющие операторы делают вашу программу компактнее и позволяют ей принимать решения. И, что еще более важно, они позволяют нам выполнять проверку на наличие ошибок. До сих пор все, что мы сделали, это писали скрипты, которые просто исполняют набор инструкций в файле. Например:
#!/bin/bash
cp /etc/foo .
echo ”Готово”
Это небольшой скрипт, назовем его bar.sh, копирует файл с именем /etc/foo в текущий каталог и выводит «Готово» на экране. Эта программа будет работать при одном условии — файл /etc/foo должен существовать. В противном случае вот что произойдет:
$./bar.sh
cp: /etc/foo: No such file or directory
Готово
Таким образом, как вы видите, есть проблема. Не у каждого, кто будет запускать вашу программу, будет файл/etc/foo. Наверное, было бы лучше, если б ваша программа сначала проверяла наличие данного файла, а затем при положительном ответе — выполняла бы копирование, в противном случае — просто бы завершала работу. В псевдо-коде это выглядит так:
если /etc/foo существует, то
скопировать /etc/foo в текущую директорию
напечатать "Готово" на экране
в противном случае,
напечатать на экране "Этот файл не существует"
выход
Можно ли это сделать в Bash? Конечно! Набор управляющих операторов Bash включает в себя:if, while, until, for и case. Каждый из этих операторов является парным, то есть начинается он одним тегом и заканчивается другим. Например, если условный оператор if начинается с if и заканчивается fi. Управляющие операторы — это не отдельные программы в системе, они встроены в bash.
if … else … elif … fi
Это один из наиболее распространенных операторов. Он позволяет программе принимать решения следующим образом — «если условие верно — делаем одно, если нет — делаем что-то другое». Чтобы эффективно его использовать, сначала нужно научиться пользоваться командой test. Эта программа выполняет проверку условия (например, существует ли файл, есть ли необходимые права доступа). Вот переписанный вариант bar.sh:
#!/bin/bash
if test -f /etc/foo
then
# Файл существует, копируем его и печатаем сообщение на экране
cp /etc/foo .
echo "Готово".
else # Файл не существует, поэтому мы печатаем сообщение
# и завершаем работу
echo "Этот файл не существует."
exit
fi
Обратите внимание на отступы строки после then и else. Они не являются обязательными, но зато делают чтение кода гораздо более простым в том смысле, что делают логику программы более наглядной. Теперь запустите программу. Если у вас есть файл /etc/foo — он будет скопирован, в противном случае будет напечатано сообщение об ошибке. Команда test проверяет существование файла. Ключ -f проверяет, является ли аргумент обычным файлом. Ниже приведен список опций test[7]:
Ключи команды test:
-d проверяет наличие файла и то, что он является каталогом
-e проверяет существование файла
-f проверяет наличие файла и то, что это обычный файл
-g проверяет наличие у файла SGID-бита
-r проверяет наличие файла и то, что он доступен на чтение
-s проверяет наличие файла и то, что его размер больше нуля
-u проверяет наличие у файла SUID-бита
-w проверяет наличие файла и то, что он доступен на запись
-x проверяет наличие файла и наличие у него прав на запуск
Оператор else используется, когда вы хотите, чтобы ваша программа еще что-то делала, если первое условие не выполняется. Существует также оператор elif, который может использоваться вместо еще одного if.elif означает «else if». Он используется, когда первое условие не выполняется, и вы хотите проверить еще одно условие.
Если вам не нравится приведенная форма записи if и test, есть сокращенный вариант.
Например, код:
if test -f /etc/foo
then
Можно записать вот так:
if [ -f /etc/foo ]; then
Квадратные скобки — это еще один вариант записи test. Если у вас есть опыт в программировании на C, этот синтаксис для вас может быть более удобным. Обратите внимание на наличие пробелов до и после каждой из скобок test[8]. Точка с запятой: «;» говорит оболочке о завершении одного оператора и начале следующего. Все, что находится после этого символа будет работать так, как будто он находится на отдельной строке. Это делает код более удобным для чтения и, естественно, что такая запись необязательна. Если вы предпочитаете другой вариант записи —then можно сразу поместить в другой строке.
Если вы используете переменные — их нужно помещать в кавычки. Например:
if [ "$name" -eq 5 ]; then
оператор -eq будет объяснен далее в этой статье.
while … do … done
Оператор while используется для организации циклов. Он работает так «пока (while) условие истинно, делать что-то». Рассмотрим это на примере:
#!/bin/bash
while true; do
echo "Нажмите CTRL-C для выхода."
done
true — это тоже программа. Единственное, что она тут делает — это запускает тело цикла снова и снова. Использование true считается медленным, потому что ваш скрипт должен запускать ее раз за разом. Можно использовать альтернативный вариант:
#!/bin/bash
while :; do
echo "Нажмите CTRL-C для выхода."
done
Это позволяет добиться точно такого же эффекта, но быстрее, потому что «:» — это встроенная функция bash. Единственное отличие состоит в принесении в жертву читабельности кода. Используйте из приведенных вариантов тот, который вам нравится больше. Ниже приведен гораздо более полезный вариант использования переменных: