Переменные
Переменные играют для аргументов команд примерно такую же роль, что и псевдонимы - для команд. То есть избавляют от необходимости мрачного ввода повторяющихся последовательностей символов. Конечно, это - далеко не единственное (а может быть, и не главное) назначение переменных, однако на данном этапе для нас наиболее существенное.
Что такое переменная? Ответ просто - некоторое имя, которому присвоено некоторое значение. Не очень понятно? - Согласен. Но, возможно, станет яснее в дальнейшем.
Имена переменных в принципе могут быть любыми, хотя некоторые ограничения также существуют. Я уже вскользь упоминал о переменных в разделе про пользователей. В частности, там, помнится, фигурировали переменные SHELL, USER, HOME. Так вот, эти (и еще некоторые) имена зарезервированы за внутренними, или встроенными, переменными оболочки (некий минимальный их набор имеется в любом шелле). То есть значения их определены раз и навсегда. и пользователем не изменяются. То есть он, конечно, может их изменить, если очень хочет - но ничего доброго, кроме путаницы, из этого не выйдет.
Таких встроенных переменных довольно много. И одна из первых по значению - переменная PATH. Это - список каталогов, в которых оболочка, в ответ на ввод пользователя в командной строке, ищет исполнимые файлы - то есть просто команды. Вы, наверное, обратили внимание, что во всех приведенных выше примерах имена команд указывались без всяких путей к ним (в отличие от файлов-аргументов, путь к которым - обязателен). Так вот, успех ее поисков и определяется списком значений переменной PATH. Каковые могут быть просмотрены командой echo
$ echo $PATH
Обратим внимание на то, что в качества аргумента команды выступает не просто имя переменной, а оно же, но предваренное символом доллара. Который в данном случае никакого отношения к приглашению командной строки не имеет, а предписывает команде echo подменить имя переменной ее значением (значениями). В данном случае вывод команды будет примерно таким:
/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
Тем временем вернемся к переменной HOME. Значение ее - полный абсолютный путь к домашнему каталогу пользователя. То есть, чтобы перейти в него, пользователю по имени alv вместо
$ cd /home/alv
достаточно набрать
$ cd $HOME
и он в своих владениях. Может показаться, что экономия - грошовая (тем паче, что перейти в собственный каталог пользователь может просто командой cd без всяких аргументов), но минуту терпения - и выгоду от использования переменных вы увидите.
Кроме переменных, предопределенных в шелле, пользователю предоставляется почти полная свобода в определении переменных собственных. И вот тут-то и наступает ему обещанное облегчение при наборе аргументов команд.
Предположим, что у нас имеется глубоко вложенный подкаталог с данными, постоянно требующимися в работе. Чисто условно примем, что путь к нему - следующий:
/home/alv/data/all.my.works/geology/plate-tectonics
Весьма удручающе для набора, даже если исправно работать табулятором для автодополнения, не так ли? Прекрасно, упрощаем себе жизнь определением переменной:
$ plate=/home/alv/data/all.my.works/geology/plate-tectonics
Дело в шляпе, Теперь, если нам нужно просмотреть состав этого каталога, достаточно будет команды
$ ls $plate
А вызвать из него любой файл для редактирования можно так:
$ joe $plate/filename
Подобно псевдонимам, переменные, определенные таким образом (то есть просто в командной строке), имеют силу только в текущем сеансе работы - по выходе из оболочки они утрачиваются. Для того, чтобы они действовали перманентно, переменные должны быть прописаны в конфигурационном файле пользовательского шелла. Однако, в отличие от псевдонимов, и этого оказывается не всегда достаточно. Ибо переменная, определенная посредством
$ NAME=Value
работает не просто только в текущем сеансе - но еще и только в конкретном экземпляре шелла. Почему и называется переменной оболочки - shell variable. Звучит это. быть может, пока не очень понятно. Однако в разделе о процессах мы уже видели, что практически любое действие в шелле - запуск команды или программы, например, - начинается с того, что оболочка, в которой это действие совершается, запускает новый экземпляр самой себя - дочерний шелл, или, как иногда говорят, субшелл.
Так вот, этот самый субшелл не наследует переменные родительской оболочки. И в итоге запущенная из командной строки программа ничего не будет знать, например, о путях к исполняемым файлам. Что автоматически ведет к невозможности запуска из нее команд просто по имени, без указания точного пути.
Чтобы избежать такой неприятной ситуации, было придумано понятие переменных окружения, или переменных среды - environment variable. Это - те переменные, которые наследуются от родительского шелла всеми дочерними программами. И чтобы сделать их таковыми, переменные следует экспортировать. Как? Командой export, которая может быть применена двояким образом. Можно сначала определить переменную:
$ NAME=Value
а затем применить к ней команду export:
$ export NAME
А можно сделать это в один прием:
$ export NAME=Value
Второй способ применяется, если нужно определить и экспортировать одну переменную. Если же за раз определяется несколько переменных:
$ NAME1=Value1; $ NAME2=Value2; ...; $ NAMEN=ValueN
то проще прибегнуть к первому способу, так как команда export может иметь сколько угодно аргументов:
$ export NAME1 NAME2 ... NAMEN
Оговорка: такой способ задания переменных действует только в POSIX-совместимых шеллах. В оболочках семейства csh для определения переменных обоих видов существуют специальные команды. Так, переменная оболочки задается командой set с указанием имени переменной и ее значения, соединенных оператором присваивания:
set EDITOR=joe
А чтобы та же самая переменная имела силу для всего окружения (то есть была бы переменной среди) потребуется другая команда:
setenv EDITOR=joe
Впрочем, традиционно имена переменных окружения задаются в верхнем регистре, переменных оболочки - в нижнем.
Каждая из этих команда, данная без аргументов, выведет список определенных переменных оболочки и окружения соответственно. А для вывода значений абсолютно всех переменных есть специальная встроенная команда - printenv.