3.6 Переменные языка
shell
Подобно большинству языков программирования,
shell
имеет переменные, которые на программистском жаргоне называются
параметрами. Такие строки, как
$1
, являются позиционными параметрами-переменными, хранящими аргументы командного файла. Цифра показывает положение параметра в командной строке. Ранее мы имели дело с другими переменными языка
shell
:
PATH
— список каталогов, в которых происходит поиск команд,
НОМЕ
— ваш начальный каталог и т.д. В отличие от переменных в обычном языке переменные, задающие позиционные параметры, не могут быть изменены; хотя
PATH
представляет собой переменную со значением
$PATH
, нет переменной 1 со значением
$1
, т.е.
$1
— это не что иное, как компактное обозначение первого аргумента.
Если забыть о позиционных параметрах, переменные языка
shell
можно создавать, выбирать и изменять. Например,
$ PATH=:/bin:/usr/bin
означает присваивание, изменяющее список каталогов в процессе поиска. До и после знака равенства не должно быть пробелов. Присваиваемое значение должно выражаться одним словом, и его следует взять в кавычки, если оно содержит метасимволы, которые не нужно обрабатывать. Значение переменной выбирается, если предварить имя знаком доллара:
$ PATH=$PATH:/usr/games
$ echo $PATH
:/usr/you/bin:/bin:/usr/bin:/usr/games
$ PATH=:/usr/you/bin:/bin:/usr/bin
Восстановим значение
$
He все переменные имеют специальное значение для интерпретатора. Можно создавать новые переменные, присваивая им значения. По традиции переменные, имеющие специальное значение, обозначаются прописными буквами, а обычные переменные — строчными. Типичным примером использования переменных является хранение в них длинных строк, таких, как имена файлов:
$ pwd
/usr/you/bin
$ dir=`pwd`
Запомним, где находимся
$ cd /usr/mary/bin
Перейдем в другое место
$ ln $dir/cx .
Используем переменную в имени файла
$ ...
Поработаем некоторое время
$ cd $dir
Вернемся
$ pwd
/usr/you/bin
$
Встроенная в интерпретатор команда
set
показывает значения всех определенных вами переменных. Для просмотра одной или двух переменных более подходит команда
echo
:
$ set
HOME=/usr/you
IFS=
PATH=:/usr/you/bin:/bin/:/usr/bin
PS1=$
PS2=>
dir=/usr/you/bin
$ echo $dir
/usr/you/bin
$
Значение переменной связано с той копией интерпретатора, который создал ее, и автоматически не передается процессам — потомкам интерпретатора.
$ x=Hello
Создание x
$ sh
Новый shell
$ echo $x
Происходит только перевод строки,
x не определено в порожденном интерпретаторе
$ ctl-d
Возврат в исходный интерпретатор
$ echo $x
Hello
x по-прежнему определено
$
Это означает, что в командном файле нельзя изменить значение переменной, поскольку выполнением командного файла управляет порожденный интерпретатор:
$ echo 'x="Good bye"
Создание shell-файла из двух строк…
> echo $x' >setx
…для определения и печати x
$ cat setx
x="Good Bye"
echo $x
$ echo $x
Hello
x есть Hello в исходном интерпретаторе
$ sh setx
Good Bye
x есть Good Bye в порожденном интерпретаторе…
$ echo $x
Hello
…но по-прежнему есть Hello в текущем интерпретаторе
$
Однако бывают ситуации, когда было бы полезно изменять переменные интерпретатора в командном файле. Очевидным примером является файл, добавляющий новый каталог к вашей переменной
PATH
. Поэтому интерпретатор предоставляет команду
'.'
(точка), которая выполняет команды из файла в текущем, а не порожденном интерпретаторе. Первоначально это было задумано для удобства пользователей, чтобы они могли повторно выполнять свой файл
.profile
, не входя заново в систему, но в принципе это открывает и другие возможности:
$ cat /usr/you/bin/games
PATH=$PATH:/usr/games
Добавим /usr/games к PATH
$ echo $PATH
:/usr/you/bin:/bin:/usr/bin
$ . games
$ echo $PATH
:/usr/you/bin:/bin:/usr/bin:/usr/games
$
Поиск файла для команды
'.'
осуществляется с помощью переменной
PATH
, так что его можно поместить в ваш каталог
bin
.
Когда используется команда
'.'
, только условно можно считать, что выполняется командный файл. Файл не "выполняется" в обычном смысле этого слова. Команды из него запускаются, как если бы вы ввели их в диалоговом режиме: стандартный входной поток интерпретатора временно переключается на файл. Поскольку файл читается, не нужно иметь право на его выполнение. Другое отличие состоит в том, что файл не получает аргументов командной строки;
$1
,
$2
и т.д. являются пустыми строками. Было бы неплохо, если бы аргументы передавались, но этого не происходит.