Shell: язык программирования и оболочка.

Лектор не рассказывал обо всех утилитах, но дал представление о том, что если мы находимся в рамках парадигмы черного ящика, то инструментальное окружение достаточно универсально. Тут возникает важный вопрос - о суперпозиции инструментов. Не хватало главного - каким образом инструменты могут быть задействованы для решения глобальных задач. Для этой цели должен быть предусмотрен инструмент для интеграции раздельный утилит и управления ими - оболочка: * манипуляция с системными объектами из одного и того же места - сценарии * работа с файлами, процессами, утилитами * работа с данными, которые обрабатываются, работа с потоками данных На самом деле, нам нужен не просто костыль для складывания команд в сценарии. Нужен язык программирования, который хорошо для этого заточен. из этого следует подход к шеллу, как к языку программирования. Но он должен быть: * алгоритмически полным.

Сценарий -- запись кс в виде файла. Надо поддерживать дисциплину, когда забиваем кс и оно работает.

3 св-во -- он должен быть достаточно высокоуровневый. На взгляд высоко и низко уровневые языки отличаются кол-вом кода(сравни си, питон, хаскель). Требование высокоуровевости говорит о том, что там должно быть как можно меньше мусора, потому что оно для решения интеграц задач, а не больших проектов.

Интерпретатор командной строки -- икс (игрека в этой лекции нет) -- он интерпретирует ком. строку, а ещё люди в нём работают, то есть он взаимодействует с пользователем, и должен это делать удобно для пользователя. Третье лектор пока не знает.

На самом деле представляется чистой случайностью, что оболочка, яп и икс стали одним инструментом под названием шелл. Исторически это неслучайно. Комбайнов в линуксе много (напр, пакетный установщик пакет не только ставит, но и собирает). Под эту базу можно и фразу подвести. Только реализуя все три функции в одном инструменте можно обеспечить полноценность каждого. Например, в досе синтаксис работы в кс и бат файлов различается, и иногда в сценарии можно то, что нельзя в кс. Это плохо. В бат ничего нельзя было делать, только извращения. Он был не алгоритмически полон(?).

Одновременно совместимость инструментальная и интерфейсная. Другие оболочки(цмд) это нарушают и делают себя маргинализованными. Шелл же универсален.

Шелл как язык программирования

Что мы знаем про сценарии в линуксе/юниксе? Это файл с # в начале, например

#!/bin/sh

Началось все с механизма запуска текстовых файлов. Шелл -- интерпретируемый яп.

Переменные

В шелле все строковые. A=B и в переменную кладется строка. Свойство оболочности добавляет интересный отпечаток. Переменную можно экспортиироовать, и она станет переменной окружения export A=BC.

Про переменные окружения -- можно управлять работой программы ключами каждой раз при запуске, но иногда удобно использовать переменные окружения COLUMNS PATH. После экспорта любой процесс может видеть эти переменные через getenv. Экспортные переменные -- аналог глобальных между скриптами.

У операции присваивания есть левая и правая часть. В правой части строки выглядят просто(без кавычек) а вот чтобы получить содержимое переменной с заданным именем надо приписывать в начале $. echo $A. "У теоретических программистов, например, принято перечеркивать не нолик, а букву о"(с)

Если вы пишете скрипт на шелле, вы ему можете передавать параметры ком строки. $0, $1, $2, $* -- первый, второй, третий, все кроме нулевого. Ещё есть эзотерический $@. Он отдает "$1" "$2" "$3" и тд. $* -- все одной строкой.

В шелле вобще много разного для удобства и не очень красивое с тз теории.

Количество параметров ком строки $#. Exit status предыдущего процесса хранится в $?. Это часть интеграторская.

Возвращаясь к теме шелл как интерпретатор -- обратите как легко и непринужденно в шелле запускать фоновые процессы. Запуск фонового процесса -- один символ, амперсанд в конце.

$!

$$

и ещё 100500.

Помимо самих операций подстановки в шелле есть куча подставлений переменных с последующей обработкой. Допустим надо вынуть начало строчки до точки. Как вы будете делать? подключите библиотеку, сделаете сплит по разделителю, возьмете нулевое. Можно вызвать внешнюю утилиту, но каждый раз --- вызывалка отвалится. ${VAR#*.} -- отрубить самый длинный хвост начинающийся с точки. Есть отрубание хвоста, головы и ещё много чего.

Всё это есть в справочниках по шеллу. Подстановка значений переменных в шелле сопровождается обработкой. В итоге в небольшом тексте можно достигнуть своих целей. (пример -- отрывание расширения)

Завязываемся на объекты с опр структурой -- имена файлов.

Отдельно к свойствам оболочки можно отнести подстановку результата вывода программы. i = $(ls) или i = ls. Перевод из потоков данных в переменные. КАк ещё можно манипулировать результатами работы программы. Перенаправлением ввода-вывода в файлы. ls > file, wc < file. А вот << это совсем другое -- спецификация входного потока в сценарии. (подать на ввод что-то от ограничителя до ограничителя, например). Ещё при такой обработке будет работать подставновка переменных. '$A' -> $A, "$A"->содержимое А.

Тут просто закрыли дескриптор, открыли в файл.

Интересней cal | wc (cal pipeline wc) . В позикс системах существуют пайпы -- каналы. Один пишет, другой читает. С тз пользователя -- программа wc обработала вывод команды cal.

Дерево трубопровода в одной строчке задать нельзя.

В позикс окружении очень много программ, которые читают с ст ввода, пишут в ст. вывод, именно потому, что их всегда можно перенаправить

Условные операторы, циклы и нет goto

if command; then command; [else command;] fi

fi операторная скобка (esac тоже).

Обратите внимания, что на месте условия стоит команда. Если последняя в цепочке команд выполнилась успещно(вернула 0), то это истина, а иначе ложь.

В итоге шелл может вообще ничего не уметь, а какая-нибудь команда умеет сравнивать, и вообще. Эта команда [. Лежит в sbin, симлинк test.

if [ "$a" ='QQ' ]; then

после [ обязателен пробел, потому что она команда.

a = eval 1+$a

Это ещё один щтрих к портрету шелла как оболочки. Если что-то может быть реализовано внешне, то оно выносится.

Но евал нетипичен, слишком часто нужен. Почти все шеллы обзавелись собственной арифметикой, а некоторые и логикой.

Тест тоже встроенный уже.

Цикл while do done

Цикл for по списку. for переменная in список; do command; done

Отдельную забавную вариацию составляет цикл for nep; Переменная пробегает значения $1 $2 $3 итд.

Про то, чем отличаются шеллы -- в след раз.

Если есть простая алг. задача (сгенерировать список от 1 до 100) то скорее всего есть утилита, которая её решает (seq).

Функции

Это просто функции, у них ничего такого нету.

1) они возвращают код возврата, а не строку. если хотите из неё что-то вернуть -- надо в ней ставить эхо, а вызов заключить в бэктик.

2)

lls(){

$1 $2 -- параметры функции

}

Функции ведут себя как утилиты, даже внутри у них разбор устроен таким образом, что они работают с позиционными параметрами.

В шелле есть обработка сигналов(можно обрабатывать CTRL-c)

ВВод-вывод

Упрощён.

read считывает по строчке со стандартного ввода. Возвращает неноль, когда заканчивается ввод.

Чего в шелле нету?

Определения собственных типов данных.

Составления графов потоков -- только через файлы.

Никакой интерфейсной поддержки кроме командной строки. Игры и граф интерфейсы на шелле - удаль молодецкая (хоть лектор и писал), он не для этого.

Шелл это хорошая оболочка для того чтобы организовывать интеграцию(алг полную) в рамках концепции инструментального окружения.

LecturesCMC/GnuLinuxArchitecture2012/Conspects/06 (последним исправлял пользователь Allena 2012-05-01 22:41:52)