Лекция №21 - основы bash программирования

На этой лекции мы начнем знакомиться с основными языковыми конструкциями bash. Знание языка bash необходимо как для изучения работы операционной системы (большинство скриптов написано на bash) так и для написания собственных скриптов.

Вы уже знаете, что скрипт должен быть исполняемым файлом и начинаться со строки #!/bin/bash. Кроме случая #!, значок # (”шарп”) - является началом комментария. Строки, которые начинаются с символа #, интерпретатор будет пропускать при обработке скрипта:

#!/bin/bash
# Это комментарий
# Это тоже комментарий

Переменные

Имя переменной в bash должно обязательно начинаться с буквы. Далее можно использовать и цифры. В bash переменные не имеют типа, поэтому объявлять переменную предварительно не нужно, а сразу можно присваивать значение:


#!/bin/bash
# Переменная
S1=Hello!
S2=”Hello World!”

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

Чтобы получить доступ к содержимому переменной, перед именем переменной ставят символ $:

echo $S1
echo $S2

В этом случае будет выполнена операция подстановки. Сначала конструкция $S2 будет заменена на Hello World, а затем будет выполнена команда echo Hello World. Операция подстановки может быть выполнена не только в случае команды echo, но и в других командах, например командах сравнения. В этом случае рекомендуется брать конструкцию $S1 в двойные кавычки - “$S1″. Позже мы подробнее рассмотрим почему. В качестве подстановки может быть использован и результат выполнения команды. Синтаксис похож - пишем символ $, а затем команду в круглых скобках без пробелов. Например: OF=/var/backup-$(date +%Y%m%d).tgz. В этом примере сначала будет выполнена команда в скобках - date +%Y%m%d, результат выполнения которой будет текущая дата в формате YYYYMMDD (например 20091217). Затем будет выполнена подставка, чтобы образовалась строка /var/backup-20091217.tgz и затем эта строка будет присвоена переменной OF.

Не забывайте, что если бы в строке были бы пробелы, то всю конструкцию следовало бы взять в двойные кавычки: OF=”/var/backup $(date +%Y%m%d).tgz”.

Переменные могут быть локальными и глобальными. Глобальные мы рассмотрели выше, а локальные описываются с помощью слова local. Рассмотрим следующий пример:

1
2
3
4
5
6
7
8
9
#!/bin/bash
STR=Hello
function echoworld {
   local STR=World
   echo $STR
}
echo $STR
echoworld
echo $STR

Результат выполнения команды будет следующий:

Hello
World
Hello

О функциях мы поговорим позже. Сейчас основное внимание на то, что хотя вывод на экран осуществляется одной и той же командой echo и одной и той же переменной STR, результат вывода разный. Так как в теле функции была объявлена локальная переменная и при обращении к ней из функции будет выводится локальное значение. Если вывод идет из тела скрипта, то выводится изначально заданное глобальное значение переменной.

Конструкция if

Для проверки условий в скрипте предназначена конструкция if. Общий синтаксис конструкции if в упрощенном виде, следующий:
if [ условие ]; then
блок команд
else
блок команд
fi

Ключевые элементы конструкции это if, then, else, fi. Точка с запятой нужна только в том случае если на одной строке расположено более одного ключевого элемента конструкции if. Если каждый ключевой элемент будет расположен на новой строке, то точка с запятой не нужна. Рассмотрим следующий практический пример:

#!/bin/bash
STR=”Hello world”
if [ $STR = "Hello world" ]
then
echo YES
else
echo NO
fi

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

[ Hello world = "Hello world" ]

Логика работы [ ] следующая: После открывающей скобки [ обязательно пробел (первый), далее до следующего пробела (второго) первое сравниваемое значение, далее оператор сравнения (например =), далее пробел (третий) и от него до следующего пробела (четвертый) второе сравниваемое значение. Сразу после четвертого пробела закрывающая скобка ] . У нас же получилось, нарушение данного правила в результате того, что в переменной STR есть пробелы. Если заключить $STR в двойные кавычки “$STR” то ошибки не будет. Исправьте скрипт и проверьте.

Конструкция сравнения [ ] выдает в результате число: 0 - если условие верное, и отличное от нуля, если неверное. Если результатом будет ноль, то выполнятся команды от then до следующей ключевой конструкции, если результат отличный от нуля, то выполнится блок команд от else до следующей ключевой конструкции. Кстати использовать конструкцию [ ] можно не только в if, но и отдельно, далее рассмотрим подобные примеры. Также хочу отметить, что [ ] более новая конструкция и имеет более старый аналог, который также часто встречается в скриптах. Это команда test. Строку if [ $STR = "Hello world" ] можно записать так: if test $STR = “Hello world”.

Чтобы посмотреть встроенную справку о конструкции if, необходимо в интерпретаторе набрать help if. Тогда будет отображена краткая справка о синтаксисе. Полностью синтаксис выглядит следующим образом:

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]… [ else COMMANDS; ] fi

Таким образом присутствует еще один ключевой элемент - elif. Предлагаю самостоятельно разобрать этот вариант и составить свой тестовый bash-скрипт с применением elif.

Конструкцию if из примера можно написать в командной строке и выполнить в интерактивном режиме. Выглядеть строка будет вот так:

STR=”Hello world”; if [ "$STR" = "Hello world" ]; then echo YES; else echo NO; fi

Так же как и в скрипте, но присутствуют точки с запятой, которые отделяют команды и ключевые элементы. Еще раз обращаю внимание на пробелы в [ ]. Чтобы не забывать об этом запомните, что [ это просто команда (наподобие любой другой команды linux), а после команды всегда идет пробел и далее ключи или параметры.

Операторы сравнения

Раз уж мы заговорили о конструкции сравнения ([ ] или test ), то самое время познакомится с операторами сравнения языка bash. С одним из них уже познакомились - это =. Рассмотрим другие.

Операторы сравнения в bash бывают арифметическими (для сравнения чисел) и операторами сравнения строк.
Арифметические операторы состоят из двух символов перед которыми стоит дефис. Ниже представлены арифметические операторы и в скобках их аналогия из языка С.

-lt - less then - меньше (<)
-gt - greater then - больше (>)
-le - less or equal - меньше или равно (<=)
-ge - greater or equal - больше или равно (>=)
-eq - equal - равно (==)
-ne - not equal - не равно (!=)

Если знакомы с английским языком, то запомнить будет несложно.

Операторы сравнения строк запомнить легче.

STR1 = STR2 - равно
STR1 != STR2 - не равно
STR1 < STR2 - меньше
STR1 > STR2 - больше
-n STR1 - возвращает 0 если строка ненулевая (имеет хотя бы один символ)
-z STR1 - возвращает 0 если строка нулевой длины.

Практический пример. Наберите и выполните в консоли следующую строку (не забывайте о пробелах!):

STR1=aaa; STR2=abc; [ "$STR1" = "$STR2" ]; echo $?

В результате вы получите число 1, которое выведет команда echo $?. Конструкция $? содержит числовой результат выполнения предыдущей команды. Предыдущая команда была [ "$STR1" = "$STR2" ] в случае выполнения условия команда возвратила бы 0, но так как условие не выполняется, то результат выполнения команды отличен от нуля.

В завершение несколько слов об операции проверки файла. Практически в каждом системном скрипте вы встретите конструкцию наподобие [ -a /etc/filename ] или [ -f "$file" ] , где file - это переменная содержащая имя файла. Это операция проверки файла или свойств файла. В качестве параметра в команде используется имя файла.

[ -f "file name" ] - возвращает 0, если файл существует и это регулярный файл
[ -e "file name" ] - возвращает 0, если файл существует
[ -w "file name" ] - возвращает 0, если файл существует и в него есть право записи

О других вариантах проверки файлов читайте в справке man bash в разделе CONDITIONAL EXPRESSIONS.

Читать другие лекции по курсу Администратор ПК с Linux

Статьи и новости схожей тематики:

Комментариев: 3

  1. ASLok:

    А есть какая-то возможность сравнить две строки в переменных “по-человечески”, т.е. когда по возрастанию сначала идет например строка “90″, а уже потом например строка “100″?

    Сейчас пишу в стиле:

    if [[ ${PACKAGES_VERSIONS[$PACKAGE_KEY]} > ${INSTALLED_VERSIONS[$PACKAGE_INSTALLED_KEY]} ]]
    then
    NOT_UPDATED=”$NOT_UPDATED $PACKAGE”
    if (( $(echo $NOT_UPDATED | wc -m) < $WIDTH ))
    then
    continue
    fi
    NOT_UPDATED=$NOT_UPDATED…
    fi

    Но возникает проблема, когда сравниваю версии, например:
    yad:
    Первое больше второго?
    ${PACKAGES_VERSIONS[$PACKAGE_KEY]}=0.9.0-1~webupd8~maverick
    ${INSTALLED_VERSIONS[$PACKAGE_INSTALLED_KEY]}=0.10.1-1~webupd8~maverick
    Да.

    Помогите пожалуйста!

    Ответить

  2. Ольга:

    Спасибо за приведенный материал по linux. Одно замечание: в строке “OF=/var/backup $(date +%Y%m%d).tgz” в кавычки нужно брать не всю строку, а то, что следует после оператора присвоения, то есть:
    OF=”/var/backup $(date +%Y%m%d).tgz”.
    Поправьте меня, если ошибаюсь.

    Ответить

    Igorka Reply:

    Ольга, спасибо, что отписались.
    Вы совершенно правы - здесь была ошибка. Уже исправил.

    Ответить

Оставьте свой отзыв