После прочтения следующих разделов вы поймете, почему в сценариях оболочки многие специальные символы присутствуют в том виде, как они написаны. Если вы пытаетесь разобраться в каком-либо сценарии оболочки и вам встречается строка, которая выглядит совершенно необъяснимо, рассмотрите ее, разбив на фрагменты.
11.3.1. Индивидуальные аргументы: $1, $2…
Переменные $1, $2, а также все переменные, названные с помощью положительных ненулевых целых чисел, содержат значения параметров сценария или аргументы. Допустим, например, что файл следующего сценария называется pshow:
#!/bin/sh
echo First argument: $1
echo Third argument: $3
Попробуйте запустить этот сценарий, как показано ниже, чтобы увидеть выводимые им аргументы:
$ ./pshow one two three
First argument: one
Third argument: three
Встроенная в оболочку команда shift может быть использована с переменными-аргументами, чтобы удалить первый аргумент ($1) и сдвинуть все оставшиеся. Конкретнее, аргумент $2 превратится в $1, $3 — в $2 и т. д. Предположим, что файл следующего сценария называется shiftex:
#!/bin/sh
echo Argument: $1
shift
echo Argument: $1
shift
echo Argument: $1
Запустите его следующим образом, чтобы понять, как он работает:
$ ./shiftex one two three
Argument: one
Argument: two
Argument: three
Как видите, сценарий shiftex выводит все три аргумента: начинает с первого, сдвигает оставшиеся и повторяет вывод.
11.3.2. Количество аргументов: $#
Переменная $# хранит количество аргументов, переданных в сценарий, и особенно важна при циклическом запуске команды shift для выбора аргументов. Если значение $# равно 0, аргументов не остается, поэтому переменная $1 пустая (см. раздел 11.6, который содержит описание циклических структур).
11.3.3. Все аргументы: $@
Переменная $@ представляет все аргументы сценария и весьма полезна для передачи их команде внутри сценария. Например, команды Ghostscript (gs) обычно длинные и сложные. Допустим вам необходимо создать шаблон команды для растрирования файла PostScript с разрешением 150 dpi, используя стандартный поток вывода, но оставив при этом также возможность для передачи других параметров в команду gs. Для этих целей можно было бы написать сценарий, подобный приведенному ниже:
#!/bin/sh
gs — q -dBATCH — dNOPAUSE — dSAFER — sOutputFile=- sDEVICE=pnmraw $@
примечание
Если какая-либо строка в сценарии оболочки становится слишком длинной для текстового редактора, можете разбить ее с помощью символа \. Например, предыдущий сценарий можно записать таким образом:
#!/bin/sh
gs — q -dBATCH — dNOPAUSE — dSAFER \
— sOutputFile=- sDEVICE=pnmraw $@
11.3.4. Имя сценария: $0
Переменная $0 хранит имя сценария, и она полезна при создании диагностических сообщений. Допустим, ваш сценарий должен сообщить о неправильном аргументе, который хранится в переменной $BADPARM. Можно вывести диагностическое сообщение с помощью такой строки, при этом в сообщении об ошибке будет указано имя сценария:
echo $0: bad option $BADPARM
Все диагностические сообщения об ошибках должны следовать в стандартную ошибку. Вспомните из подраздела 2.14.1 о том, что синтаксис 2>&1 перенаправляет стандартную ошибку в стандартный вывод. Для записи в стандартную ошибку можно обратить этот процесс с помощью синтаксиса 1>&2. Чтобы использовать его в предыдущем примере, примените такую строку:
echo $0: bad option $BADPARM 1>&2
11.3.5. Идентификатор процесса: $$
Переменная $$ хранит идентификатор процесса оболочки.
11.3.6. Код выхода: $?
Переменная $? хранит код выхода последней команды, которую выполнила оболочка. Коды выхода, играющие важную роль в освоении сценариев оболочки, рассмотрены далее.
11.4. Коды выхода
Когда команда Unix завершает работу, она оставляет для родительского процесса, который запустил эту команду,
Оболочка хранит код выхода последней команды в специальной переменной $? поэтому его можно узнать из командной строки:
$ ls / > /dev/null
$ echo $?
0
$ ls /asdfasdf > /dev/null
ls: /asdfasdf: No such file or directory
$ echo $?
1
Вы видите, что успешно завершившая работу команда вернула значение 0, а команда с ошибкой вернула значение 1 (при условии того, что в вашей системе нет каталога /asdfasdf).