Краткий обзор шелла как ЯП
Нынче немодно говорить, что шелл --- полный ЯП, а BAT --- неполный. Говорят, что CMD полный.
Поговорим про то, что такое скрипт --- сценарий с т. з. юних систем. Уже говорилось, что в юних, а в след за ним и в линух свойство файла быть запускаемым опр. специальным режимом доступа (использование). При этом этот файл внутри себя может быть как бинарником, а может быть и текстовым. Для вып. этого файла запускается интерпретатор, который его интерп. По умолчанию этот интерпретатор --- шелл. Именно поэтому, когда говорят скрипт, имеют в виду шеллскрипт. Это искл, которому доверять не надо. В линух принято след. правило: сценарий --- файл, который начинается с #!<интерпретатор>/ "то первая строка файла, например #!/bin/sh. Эта строчка позволяет системе решить,что этот файл должен исполняться соотв. интерпретатором. Запустили prog 1 2 3, а у prog написано #!/bin/sh, то запустится на самом деле /bin/sh prog 1 2 3, причём шелл делает так, что список аргументов начинается с prog. На самом деле, скрипты пишутся на чём угодно: perl, python, ..., лишь бы интерпретатор проигнорировал sha-bang (эту самую первую строчку). Отсюда замечательное свойство --- во многих языках строка с решётки --- комментарий. Ещё одно свойство --- сказав chmod +x, сделал из скрипта программу.
Практически на тех же правах, что и перем. окруж, определяется куча пареметров разных, в том числе для работы ... . Переменная $0 будет соотв. нулевому аргументу, $1 --- первому, и так далее до 9. Ещё есть такая команда shift, которая без параметров производит сдвижку на 1 параметр вправо (2 в 1, 3 в 2, ..., 10 в 9). Зачем это нужно: у вас там флаги, потом имена файлов. Вы флаги прошифтили, а дальше только имена файлов, можно обрабатывать их в цикле. $* --- строка целиком. $@ тоже содержит строку целиком, заведена она для того, чтобы операцию подстановки внутри кавычек. Разница при квотировании: "$*" --- одна большая строка ("$1 $2 $3"), а результатом "$@" будут отдельные параметры ("$1" "$2" "$3"). Если посмотреть на $@ то кажется, что это специфическая, контексно-зависимая штука, потому что работает иначе, но пользоваться этим удобно. Что ещё есть: $# --- количество параметров командной строки.
- $_ --- последняя введённая польз. строка
- $$ --- pid запущенного процесса.
- $! --- pid последнего из процессов, запущенных в фоне
Списки
Списки --- списки команд. Если захотелось, чтобы несколько команд работало вместе, например, чтобы они выводили в один файл. Можно сделать
cmd1 > f cmd2 >> f ...
а можно сделать
{cmd1; cmd2;} > f
Про скобки: можно рассматривать их как операторные скобки. Одно из свойств фигурных скобок состоит в том, что ввод-вывод объединяется. Если для того, чтобы запустить эти команды, не надо запусктаь отдельного шелла, то они выполн. в текущем. Но если нужно, то запускаются отдельно: echo ... | read A, то ... .Если же записать круглые скобки: (cmd1; cmd2) > f, то обязательно запускается отдельный шелл. Этод удобно для того, чтобы понаопределять переменных, а потом всё забыть
Условный оператор
if <список>; then <список>; [else <список>;] fi
Точки в запятыми обязательными, чтобы шелл не посчитал then очередным параметров. Встаёт вопрос, когда выполняется then, в других else. Все мы знаем,что 0 --- ложь, всё остальное --- истина. В типизированных языках есть специальный тип. Шелл заточен под работу с программами, поэтому он использует exit status. Программа по завершении возвращает exit status. Существует ячейка, которую программа по окончанию работы она заполняет всегда. Код завершения последней запущенной программы лежит в $?. На exit status распрост. след правило: если он равен 0, то программа заверш. успешно, иначе рпограмма завершилась ошибкой с кодом exit status. Условная команда в шелл выаолн. список команд, и елси он выполняется успешно, то выполняется then, иначе else. Как опр. код заверш. в списке --- по последней команде. Если код завершения --- 0, то выполняется then, иначе else.
Два амперсенда --- более короткий способ записи условного оператора. Последовательность команд может быть объединена не точками с запятыми, а && или ||. Те, кто программировал в си, знает, что там ленивое вычисление лог. выр. В шелле в a || b b выполняется тогда, кгда a завершилдась неуспешно, в && наоборот.
Пример:
test -r logfile && cat logfile || echo File not found
Цикл
while <список>; do <список>; done
Есть break, continue. У каждой есть необязательный параметр, из скольки циклов выскочить. Более сложно устроен for.
for <переменная> in <строка>; do <список>; done
Пример:
for n in `ls`; do echo $n; done
Тут встречаемся с тем, что разделителем в том числе является и перевод строки
case
case <список> in <шаблон>) список ;; ... esac
При всём некрасивом синтаксисе, на самом деле, жутко удобная штука, потому что используются wildcards, т.е. производится сопоставление шаблонов.
Функции
<имя>() { ... $1 --- первый позиционный параметр функции }
trap
В шелле есть команда trap, которая позволяет перехватывать сигналы, посылаемые процессы. Синтаксис:
trap <функция> сигнал
B тогда обработчик --- не система, а функция. Никаких специфич. парам. там нет. Единственное, среди списка сигналов есть специальное слово EXIT, которое словом не является, а является флагом выхода из скрипта, функция ыполняется после завершения скрипта. Для чего это нужно --- для того, чтобы удалять файлы, созданные mktemp, например. Делается это следующим образом: пишется функция, которая создаёт временный файл и добавляет его в переменную, написать
onexit() { trap - EXIT; cleanfile}
Первым делом в ней нужно отключить обработку EXIT, иначе shell будет бесконечно этот обработчик вызывать.
ДЗ: привести пример, что можно, или доказать, что нельзя с использованием сигналов сделать очередь для диспетчеризации процессов на разные процессоры...
Сведения о ресурсах
Продолжительность (ак. ч.) |
Подготовка (календ. ч.) |
Полный текст (раб. д.) |
Предварительные знания |
Level |
1 |
1 |
1 |
|
1 |