Программирование в shell


Каждый процесс имеет среду, в которой он выполняется. shell
использует ряд переменных этой среды.
Если вы наберете команду "set" без параметров, то на экран
будет выдана информация о ряде стандартных переменных, созданных
при входе в систему (и передаваемых далее всем вашим новым
процессам "по наследству"), а также переменных, созданных и
экспортируемых вашими процессами.
Конкретный вид и содержание выдаваемой информации в немалой
степени зависит от того, какая версия UNIX используется и как
инсталлирована система.
Вот лишь часть того, что выдала мне команда "set":

HOME=/home/sae
PATH=/usr/local/bin:/usr/bin:/bin:.:/usr/bin/X11:
IFS=

LOGNAME=sae
MAIL=/var/spool/mail/sae
PWD=/home/sae/STUDY/SHELL
PS1=${PWD}:" "
PS2=>
SHELL=/bin/bash
TERM=linux
TERMCAP=console|con80x25|dumb|linux:li#25:co#80::
UID=501
perem=stroka
x=5

Прокомментируем эти присваивания значений переменным.

HOME=/home/sae - это имя домашнего директория, в котором
пользователь (в данном случае я) оказывается после входа в
систему. То есть, правильно набрав имя и пароль, я окажусь в
директории "/home/sae".

PATH=/bin:/usr/bin:.:/usr/local/bin:/usr/bin/X11 - эта
переменная задает последоватьельность файлов (ТРОПУ), которые
просматривает "shell" в поисках команды. Имена файлов разделяются
здесь двоеточиями. Последовательность просмотра соответствует
очередности следования имен в тропе. НО ПЕРВОНАЧАЛЬНО поиск
происходит среди так называемых встроенных команд. В число
встроенных команд входят наиболее часто используемые команды,
например "echo", "cd", "pwd", "date". После этого система
просматривает директорий "/bin", в котром могут находиться
команды "sh", "cp", "mv", "ls" и т.п. Затем директорий "/usr/bin"
с командами "cat", "сс", "expr", "nroff", "man" и многими
другими. Далее поиск происходит в текущем директории (".", или
другое обозначение - "пусто", т.е.""), где скорее всего находятся
написанные вами команды (расчеты).
После набора командной строки и нажатия "shell"
(после выполнения необходимых подстановок) распознает имя,
соответстующее команде и осуществляеет ее поиск в директориях,
перечисленных в тропе. Если команда размещена вне этих
директориев - она не будет найдена. Если присутствует несколько
команд с одинаковым именем, то вызвана будет та, которая
расположена в директории, просматриваемом первым.
Тропу, как и прочие перемнные, можно легко менять, добавляя,
переставляя или исключая директории. (Кстати, представленная
тропа получена из "настоящей" путем сокращений и перестановок).

IFS= - (Внутренний Разделитель Полей) перечисляет символы,
которые служат для разделения слов (полей). Таковыми являются
"пробел", "табуляция" и "перевод строки", поэтому здесь слева от
присваивания ничего не видно и занято две строки.

LOGNAME=sae - имя входа ("имя" пользователя).

MAIL=/var/spool/mail/sae - имя файла, в который поступает
(электронная) почта.

PWD=/home/sae/STUDY/SHELL - имя текущего директория

PS1=${PWD}:" " - вид промтера. В данном случае в промптере
будет выдаваться имя текущего директория двоеточие и пробел. То
есть здесь будет "/home/sae/STUDY/SHELL: ".

PS2=> - этот промтер (эдесь ">") используется как
приглашение к продолжению ввода (в очередной строке)
незаконченной команды. Например, наберите открывающую скобку "("
и после нажатия в следующей строке вы увидите этот
промптер. Если пока не знаете, что дальше делать, наберите
закрывающую скобку ")" - и он исчезнет.

SHELL=/bin/bash - эта переменная указывает оболочку, которую
использует пользователь. В данном случае используется не
(стандартный) shell ("sh"), а "продвинутая" версия - "bash",
написанная тем же автором (Bourne-Again SHell).

TERM=linux - указание типа терминала.

TERMCAP=console|con80x25|dumb|linux:li#25:co#80:: -
(TERMinal CAPacity) это (очень сильно) обрезанная строка задания
параметров терминала.

UID=501 - идентификатор пользователя (мой - "501").

Perem=stroka
x=5 - переменные, которые ввел пользователь.

Исходная среда устанавливается автоматически при входе в
систему с использованием файлов типа "/etc/rc" и "/etc/.profile".
ВАЖНОЕ ЗАМЕЧАНИЕ. Один из способов просто изменит среду
(например, тропу поиска команд, вид промтера, вид оболочки, цвет
экрана и т.п.) можно, разместив эту информацию в своем домашнем
директории в специальизированном файле ".profile"
(${HOME}/.profile), присвоив нужные значения переменным среды. То
есть вызвать это файл в редактор и написать, что пожелаете).
Тогда при каждом вашем входе в систему этот файл будет
автоматически выполняться и устанавливать новую среду. Этот файл
должен ОБЯЗАТЕЛЬНО размещаться в вашем ДОМАШНЕМ директории
(директории входа).
Если вы внесли изменения в ".profile", то для переноса этих
изменений в среду необходимо выполнить этот файл. Для этого можно
выйти и заново войти в систему, а можно воспользоваться
(специально для этого случая созданной) командой "." без выхода
из системы, т.е.

. .profile

Следует иметь в виду, что имена файлов, начинающиеся с
точки, вообще имеют особый статус. Так, они не выдаются на экран
простой командой "ls" - необходимо вызывать эту команду с флагом
"-a". Кстати, и не уничтожаются огульно командой "rm *".

Дописать новый совй директорий "my" в тропу команд можно,
записав в ".profile", например

PATH=${PATH}:/home/sae/my

Или

PATH=${PATH}:${HOME}/my

Как правило, устанавливаемые переменные среды следует
экспортировать. Например,

Export TERM PATH REDKEYS MAIL

Кроме определения переменных в ".profile" можно выполнить
команды, например команда
stty -lcase
установит терминал в режим "большие и маленькие буквы"; а команда
cat заставка
выдаст на экран заставку , которую вы сами подготовите в
файле "заставка" с учетом ваших эстетических пристрастий и
художественных способностей.


Сам интерпретатор shell автоматически присваивает значения
следующим переменным (параметрам):
? - значение, возвращенное последней командой;
$ - номер процесса;
! - номер фонового процесса;
# - число позиционных параметров, передаваемых в shell;
* - перечень параметров, как одна строка;
@ - перечень параметров, как совокупность слов;
- - флаги, передаваемые в shell.
При обращении к этим переменным (т.е при использовании их в
командном файле - shell-программе) следует впереди ставить "$".
Пример. Вызов расчета

Specific par1 par2 par3

Имеющего вид

###
# specific: Специальные параметры (переменные)

Echo $0 - имя расчета
echo $? - код завершения
echo $$ - идентификатор последнего процесса
echo $! - идентификатор последнего фонового процесса
echo
echo $* - значения параметров, как строки
echo $@ - значения параметров, как слов
echo
set -au
echo $- - режимы работы интерпретатора

Выдаст на экран

Specific - имя расчета
0 - код завершения
499 - идентификатор последнего процесса
98 - идентификатор последнего фонового процесса

Par1 par2 par3 - значения параметров, как строки
par1 par2 par3 - значения параметров, как слов

Au - режимы работы интерпретатора


Код "0" соответсвует нормальному завершению процесса.
Важную роль при создании уникальных файлов играет
специальная переменная "$$", значение которой соответствует
номеру процесса, выполняющего данный расчет. Каждый новый расчет,
выполняемый компьютером, инициирует один или несколько процессов,
автоматически получающих номера по-порядку. Поэтому, используя
номер процесса в качестве имени файла, можно быть уверенным, что
каждый новый файл будет иметь новое имя (не запишется на место
уже существующего). Достоинство является и главным недостатком
такого способа именования файлов. Неизвестно, какие имена будут
присвоены файлам. И, если в рамках данного процесса можно найти
файл "не глядя", т.е., обратившись к нему, используя $$, то потом
такие файлы можно легко потерять. Это создает дополнительные
проблемы при отладке программ.
"echo" без параметров выводит пустую строку.
Различия $* и $@ состоит в том, что певая переменная может
быть представлена как

"par1 par2 par3"

А вторая как

"par1" "par2" "par3"

Пример, иллюстрирующий различия "$*" и "$@" будет рассмотрен
в связи с оператором "for".
Для иллюстрации мы установили командой "set" режимы
интерпретатора ("a" - все последующие переменные экспортируются;
"u" - отсутствие параметра считать ошибкой), что и отразилось в
специальной переменной "$-".