Переменные играют для аргументов команд примерно такую же роль, что и псевдонимы - для команд. То есть избавляют от необходимости мрачного ввода повторяющихся последовательностей символов. Конечно, это - далеко не единственное (а может и не главное) назначение переменных, однако на данном этапе для нас наиболее существенное.
Что такое переменная? Ответ просто - некоторое имя, которому присвоено некоторое значение.
Имена переменных в принципе могут быть любыми, хотя некоторые ограничения также существуют. Некоторые имена зарезервированы за внутренними, или встроенными, переменными оболочки (некий минимальный их набор имеется в любом шелле). То есть значения их определены раз и навсегда. и пользователем не изменяются. То есть он, конечно, может их изменить, если очень хочет - но ничего доброго, кроме путаницы, их этого не выйдет.
Таким встроенных переменных довольно много. И одна из первых по значению – переменная PATH. Это - список каталогов, в которых оболочка, в ответ на ввод пользователя в командной строке, ищет исполнимые файлы - то есть просто команды. Вы, наверное, обратили внимание, что во всех приведенных выше примерах имена команд указывались без всяких путей к ним (в отличие от файлов-аргументов, путь к которым - обязателен). Так вот, успех ее поисков и определяется списком значений переменной PATH, которые могут быть просмотрены командой echo
# echo $PATH
Обратим внимание на то, что в качества аргумента команды выступает не просто имя переменной, а оно же, но предваренное символом доллара. Который, в данном случае, никакого отношения к приглашению командной строки не имеет, а предписывает команде echo подменить имя переменной ее значением (значениями). В данном случае вывод команды будет примерно таким:
/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
Тем временем вернемся к переменной PATH Значение ее - полный абсолютный путь к домашнему каталогу пользователя. То есть, чтобы перейти в него, пользователю по имени alv вместо
# cd /home/alv
достаточно набрать
# cd $HOME
и он в своих владениях. Может показаться, что экономия - грошовая, но минуту терпения - и выгоду от использования переменных вы увидите.
Кроме переменных, предопределенных в шелле, пользователю предоставляется почти полная свобода в определении переменных собственных. И вот тут-то и наступает ему обещанное облегчение при наборе аргументов команд.
Предположим, что у нас имеется глубоко вложенный подкаталог с данными, постоянно требующимися в работе. Условимся, что путь к нему - следующий:
Весьма удручающе для набора, даже если исправно работать табулятором для автодополнения, не так ли? Прекрасно, упрощаем себе жизнь определением переменной:
Дело в шляпе, Теперь, если нам нужно просмотреть состав этого каталога, достаточно будет команды
# ls $PLATE
А вызвать из него любой файл для редактирования можно так:
# vim $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
Нам еще не раз придется обращаться к вопросу о переменных. Однако для начала сказанного, наверное, достаточно.
Существуют и иные способы присвоения значений переменным. Одно неизменно - значение переменной это строка. Например, значение переменной можно присвоить используя строку вывода некоторой команды.
variab3=`cat /var/run/inetd.pid`
Здесь переменной variab3 присваивается значение вывода, полученной от команды, заключенной в одинарные кавычки. В данном случае значение переменной variab3 будет PID демона inetd. Значение переменной можно получить и интерактивно, т.е. с клавиатуры.
echo -n "Введите свое имя" read username
При запуске командный интерпретатор выведет строку "Введите свое имя" и будет ждать ввода с клавиатуры. Строка, введенная пользователем, и будет значением переменной username. Вообще говоря, read может присвоить значения сразу нескольким переменным.
echo -n "Введите свое имя и фамилию" read username userfamname
Если пользователь введет свое имя и фамилию через пробелы, то переменным username и userfamname присвоятся соответственно строки с именем и фамилией пользователя. Если же введенных значений больше чем определено read, они игнорируются. В случае же пустых присвоений, значение переменной также пусто.
При использовании любой переменной Shell подставляет ее значение. Существуют также и более сложные конструкции получения непосредственно значения переменной.
$variable - Значение variable, или ничего если переменная не определена.
${variable} - Аналогично, с отделением имени variable от последующих символов.
${variable:-string} - Значение variable, если переменная определена. В противном случае string. Значение variable остается неизменным.
${variable:=sring} - Значение variable, если переменная определена. В противном случае string, при этом variable присваивается значение string.
${variable:?string} - Так называемая "обязательная переменная". Если variable не определена, выводится строка string и интерпретатор прекращает работу. Если же и строка string пуста, в таком случае выводится variable: parameter not set
${variable:+string} - Строка string, если переменная variable определена. В противном случае ничего.