Программирование в стандарте POSIX


Переменные и аргументы shell-процедур


Переменные обозначаются именами. Значения могут присваиваться им привычным способом, то есть посредством команд вида:

имя=значение [имя=значение] ...

Все значения в языке shell трактуются как текстовые. Подчеркнем, что, в соответствии с этими требованиями, конструкция

имя=значение

должна представлять собой одно слово - в ней не может быть пробелов.

Обычно в языках программирования ясно из контекста, где подразумевается имя переменной, а где значение. Так, в левой части оператора присваивания обычно используется имя, в правой - значение. В shell все не так. Переход от имени переменной к значению помечается посредством явной операции $. Если в команде встречается конструкция

$имя

то вместо нее интерпретатор shell подставляет значение переменной с указанным именем. Допускается и запись

${имя}

с тем же смыслом, если нужно отделить имя от последующего текста.

Рассмотрим пример. После выполнения команд (см. листинг 2.6) - утилита echo (эхо) выдает на стандартный вывод свои аргументы - на экране появится результат вывода значений переменных (см. листинг 2.7).

a=value_of_variable b=1+2 echo a = $a echo b = $b

Листинг 2.6. Присваивание и извлечение значение переменных. (html, txt)



a = value_of_variable b = 1+2

Листинг 2.7. Результат вывода значений переменных. (html, txt)

Значения формальных аргументов shell-процедур обозначаются как

$цифра

$0 - это имя интерпретируемой shell-процедуры. Если заданных при вызове команды фактических аргументов меньше, чем 9, "лишние" формальные аргументы получают пустые значения. О том, как добраться до фактических аргументов с номерами большими, чем 9, будет сказано ниже (см. управляющую конструкцию for и команду shift).

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

echo Имя команды: $0 echo Значение первого аргумента: $1 echo Значение второго аргумента: $2 echo Значение третьего аргумента: $3

Листинг 2.8.
Пример shell-процедуры. (html, txt)

Пусть приведенный текст помещен в файл с именем three_args. Тогда после выполнения команды (см. листинг 2.9) на экране появится ее результат (см. листинг 2.10).

three_args arg1 . - arg4

Листинг 2.9. Пример вызова shell-процедуры с аргументами. (html, txt)

Имя команды: three_args Значение первого аргумента: arg1 Значение второго аргумента: . Значение третьего аргумента: -

Листинг 2.10. Результат выполнения shell-процедуры. (html, txt)

Поскольку в тексте shell-процедуры упомянуты только первые 3 аргумента, значения аргументов с большими номерами (даже если они заданы, как в приведенном примере) не влияют на ее работу.

Команда

three_args arg1 --

выдаст другой результат (см. листинг 2.11):

Имя команды: three_args Значение первого аргумента: arg1 Значение второго аргумента: -- Значение третьего аргумента:

Листинг 2.11. Еще один результат выполнения shell-процедуры. (html, txt)

Значение третьего формального аргумента пусто.

Прежде чем начнется выполнение командной строки, т. е. будет вызвана заданная в ней команда, строку обрабатывает shell, выполняющий в ней некоторые подстановки. С одной из них - значения переменной вместо конструкции $имя - мы уже познакомились. Язык shell содержит ряд аналогичных конструкций. Рассмотрим их.

Там, где в командной строке встречается запись вида

${имя:-слово}

вместо нее подставляется значение переменной с указанным именем, если это значение непусто, в противном случае подставляется слово. Например, при наличии в shell-процедуре присваивания

initdir=${1:-/}

переменная initdir получит значение первого аргумента, если оно непусто. Если же процедуру вызвали без аргументов, значением initdir станет символ /. Подобные конструкции - удобный способ использования подразумеваемых значений.

Запись вида

${имя:=слово}

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


Вместо всей конструкции в командную строку подставляется итоговое (непустое старое или присвоенное новое) значение переменной.

Конструкция

${имя:?слово}

предназначена для выдачи в стандартный протокол сообщения об ошибке, если значение переменной с заданным именем не установлено или пусто, после чего неинтерактивный shell завершает работу с ненулевым кодом возврата. Непустое значение подставляется в командную строку, и интерпретация командного файла продолжается обычным образом.

Вместо конструкции

${имя:+слово}

подставляется слово, если значение переменной с заданным именем непусто; в противном случае не подставляется ничего. Такой способ удобен для использования альтернативных значений.

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

Shell содержит базовые средства для обработки цепочек символов. Так, вместо конструкции

${#имя}

подставляется число символов в значении переменной с заданным именем.

Предоставляется четыре конструкции для сопоставления с образцом:

${имя%слово} ${имя%%слово} ${имя#слово} ${имя##слово}

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

Приведем несколько примеров. Для их понимания достаточно знать, что шаблон * сопоставляется с произвольной цепочкой символов, в том числе с пустой.

После присваивания переменной

HOME=/home/galat

команда

echo ${#HOME}

выдаст 11.

Заменить в имени файла суффикс .f на .for можно с помощью команд, показанных в листинге 2.12:

f=file.f mv $f ${f%.f}.for

Листинг 2.12. Пример сопоставления с образцом. (html, txt)

Выдать первый элемент маршрутного имени файла (см. далее) можно с помощью команд, показанных в листинге 2.13:

f=маршрутное_имя echo ${f%%/*}

Листинг 2.13. Второй пример сопоставления с образцом. (html, txt)

Последний элемент выдается командой, приведенной в листинге 2.14:

echo ${f##*/}

Листинг 2.14. Третий пример сопоставления с образцом. (html, txt)


Содержание раздела