Настройка и работа в Linux
adb5321d

Переменные


Начнем с отличий между переменными bash и командного языка DOS. Их удобно продемонстрировать на примере.

Рассмотрим команду, которая «дописывает» в переменную окружения CLASSPATH путь к архиву JAVApackage (подобные команды часто вставляются в конфигурационные файлы инсталляторами различных программ). В DOS она имела бы приблизительно следующий вид:

set CLASSPATH=%CLASSPATH%;c:Program FilesBig Program JAVApackage.jar

А в «версии для Linux» она может выглядеть так:

CLASSPATH=”$CLASSPATH${CLASSPATH:+:} /opt/big-program/ JAVApackage.zip” export CLASSPATH

или так:

export CLASSPATH=”$CLASSPATH${CLASSPATH:+:}/opt/ big-program/JAVApackage.zip”

Как видим, в DOS переменные ограничиваются с двух сторон символами ‘%’, а в bash маркируется только их начало — символом ‘$’: признаком конца служит первый символ, не разрешенный в именах переменных (разрешены буквы, цифры и символ подчеркивания). Кроме того, в bash нет команды, аналогичной SET: интерпретатор распознает присваивание значения переменной просто по наличию знака равенства.

Кстати, благодаря тому, что установка переменной окружения в bash не требует отдельной команды, ее можно сделать частью любой команды (рис. 2). Присвоенное таким образом значение действительно только для данной команды, а в среду bash изменения не вносятся.

Рис. 2. Присваивание значения переменной окружения может быть не только отдельной командой, но и частью другой команды

Вернемся, однако, к нашему примеру. Несмотря на более короткую форму записи самих переменных и операции присваивания, «Linux-версия» оказалась длиннее. Во-первых, там, где командный язык DOS обходится одним-единственным знаком ‘;’, она содержит устрашающего вида конструкцию ${CLASSPATH:+:}, а во-вторых, в ней присутствует несколько загадочная для пользователя DOS команда export.

И то, и другое — следствие заботы о безопасности. Команда export делает переменную доступной другим командам. В командных файлах DOS переменные всегда внешние, и в подавляющем большинстве случаев это действительно нужно, поскольку переменные служат почти исключительно для обмена данными между программами. В bash же широко используются внутренние переменные — в качестве счетчиков, для хранения промежуточных результатов вычислений или имен файлов и т. д. Поэтому переменные, которые должны быть доступны за пределами данного скрипта, специальным образом отмечаются. Конечно, маловероятно, что имя внутренней переменной случайно совпадет с именем переменной окружения, в результате чего значение последней окажется испорченным и какая-то программа начнет работать неправильно, но, как говорил Козьма Прутков, «лучше перебдеть, чем недобдеть».


Конструкция ${CLASSPATH:+:} вставляет в строку двоеточие (которое в bash служит разделителем элементов CLASSPATH, а также PATH, играющей ту же роль, что и в DOS), но лишь при условии, что строка CLASSPATH не является пустой. Без этой меры предосторожности результатом выполнения команды могла бы оказаться переменная CLASSPATH вида :/opt/big-program /JAVApackage. zip, т. е. с пустым элементом в начале. Такой элемент обозначает текущий каталог, который в Linux, в отличие от DOS, необходимо включать в CLASSPATH (и в PATH) в явной форме. Причем в большинстве дистрибутивов это не делается — из тех же соображений «как бы чего не вышло».

Данное обстоятельство часто сбивает с толку начинающих пользователей Linux:

— Как же так: я ведь и атрибуты executable for all на файл MyGreatCommand поставил, и в первой строке #!/bin/sh написал, а мне все равно говорят: command not found!

— Конечно! Ведь ты же ее в PATH не поместил!

— Какой PATH? Она у меня в текущем каталоге!

— А у тебя разве текущий каталог входит в PATH?

— ???

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

Если в DOS с переменной можно сделать, грубо говоря, две вещи — присвоить ей значение и извлечь значение, присвоенное ранее, — то в bash вариантов намного больше: скажем, извлечь значение можно десятком разных способов, включая условное извлечение (с которым мы познакомились на примере конструкции ${CLASSPATH:+:}), извлечение подстроки и извлечение с использованием шаблона. В частности, конструкция ${X##шаблон} позволяет, извлекая строку, удалить из нее максимально возможную соответствующую шаблону подстроку, считая от начала, а ${X%шаблон} — минимально возможную, считая с конца. Так что отсечь «хвосты» упомянутым в предыдущем разделе именам файлов можно было бы, например, следующим образом:

for i in /bin/*.static do j=${i##*/} cp ”$i” ”${j%.static}” done

Подробнее о разных вариантах извлечения переменных рассказывается во врезке на с. 156. А операторами for и do мы займемся во второй части статьи.


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