Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

Программирование на Shell. Скрипты.

1. Введение

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

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

    Bourne shell (sh), названная в честь своего создателя Стивена Борна из AT&T Bell Labs. С shell (csh), разработанная Биллом Джоем, первоначально была создана для BSD UNIX, сейчас входит в состав System V. Korn shell (ksh), созданная Дэвидом Корном на бозе оригинальной bsh, но также реализующая и некоторые возможности оболочки С.

Помимо перечисленных выше основных оболочек, встречаются некоторые другие. Поскольку в своей работе вы можете столкнуться с ними, ниже приводится их перечень.

    Обновлённый вариант Bourne shell - Bourne Again (bash) - созданный в рамках проекта GNU. Pd-ksh (pdksh) - общедоступная версия Korn shell компании AT&T. Несмотря на то, что Pd-ksh представляет собой клон Korn shell, она лишена ряда возможностей, которые делают Korn shell мощным инструментом для написания сценариев (script). TC shell (tcsh) - расширенная версия C shell. В этой версии реализованы несколько новых возможностей, отсутствующих в C shell, например редактирование командной строки и проверка орфографии. Z shell (zsh) - оболочка, объединяющая в себе многие возможности оболчки Bourne Again, TC shell, Korn shell и предлагающая ряд новых средств. Более всего Z shell похожа на Korn shell.

2. Основные понятия языка shell

2.1. Ввод-вывод

Три направления ввода-вывода являются выделенными - стандартный ввод, стандартный вывод и стандартный протокол. Как правило, команды берут исходные данные из стандартного ввода и помещают результаты в стандартный вывод.

НЕ нашли? Не то? Что вы ищете?

Стандартный вывод - это монитор вашего терминала на который данные выводятся после выполнения команд, а стандартный ввод - клавиатура, с которой вы вводите данные, и с которой эти данные считываются программой.

Стандартные ввод, вывод и протокол можно переназначить. Обозначение

< <имя файла>

служит для переназначения стандартного ввода (дескриптор файла 0),

> <имя файла>

для стандартного вывода (дескриптор файла 1);

<< <строка>

ввод происходит со стандартного ввода, пока не встретится указанная <строка> или конец файла,

>> <имя файла>

для стандартного вывода; если файл существует, то выводимая информация добавляется к конец этого файла,

<& <цифра>

в качестве стандартного ввода объявляется файл, ассоциированный с дескриптором <цифра>; аналогично для стандартного вывода

>& <цифра>

<&- и >&-

закрывают соответственно стандартный ввод и вывод.

Если любой из этих конструкций предшествует цифра, то с указанным файлом будет ассоциирован дескриптор, равный указанной цифре, вместо 0 и 1 по умолчанию. Например,

2 > <имя файла>

для стандартного протокола используется дескриптор 2, а

2 >& 1

ассоциирует дескриптор 2 с файлом, ассоциированным с дескриптором 1.

... 2>protocol

переназначает стандартный протокол (дескриптор 2) в файл по имени protocol.

Чтобы переназначить стандартный протокол туда же, куда уже назначен стандартный вывод, следует употребить конструкцию

... 2>&1

Важен порядок переназначения: shell производит переназначение слева направо по указанному списку. Так,

1 > xxx 2 >& 1

сначала ассоциирует дескриптор 1 с файлом xxx, а затем дескриптор 2 с 1, т. е. тоже с xxx. А

2 >& 1 1 > xxx

ассоциирует дескриптор 2 с терминалом, а 1 - с файлом xxx.

Можно переназначить системный ввод на текущий файл:

isql - - <

Примеры использования перенозначения стандартного ввода-вывода:

·  echo < my - данные из файла my выводятся на экран;

·  echo "Error" > my. lst - запись строки "Error" в файл my. lst;

·  "Any symbols you want" >> file - строка добавляется в конец файла file, если он существует

2.2. Синхронное и асинхронное выполнение команд

Обычно shell ждет завершения выполнения команды. Однако имеется возможность запустить задачу в асинхронном режиме, т. е. без ожидания ее завершения. Для этого после команды (после всех ее аргументов и указаний о переназначении ввода-вывода) надо поставить знак &. При этом по умолчанию стандартный ввод команды назначается на пустой файл /dev/null.

Пример: создать файл primer можно по команде

echo > primer

Еще пример: запустить программу prog в асинхронном режиме, чтобы не надо было дожидаться его завершения, засечь время выполнения, результаты программы направить в файл prog. res, данные о времени выполнения - в файл prog. tim.

time prog > prog. res 2> prog. tim &

2.3. Конвейер

Конвейер - последовательность команд, разделенных знаком |. Если после конвейера стоит ";" , shell ждет его завершения. Если "&" - то не ждет. Роль ";" может играть конец строки. Смысл конвейера в том, что стандартный вывод одной команды замыкается на стандартный ввод другой.

Примеры конвейеров команд:

ls *.o | wc - l - подсчитать число объектных файлов в текущем каталоге;

who | sort - печать отсортированного списка пользователей;

who | grep you - поиск определённого пользователя;

who | grep you | wc - l - подсчёт: сколько раз пользователь you входил в систему.

2.4 Метасимволы, генерация имен файлов

Метасимволы - символы, имеющие специальное значение для интерпретатора :

? * ; & ( ) | ^ < > <пробел> <табуляция> <возврат_каретки>

Однако каждый из этих символов может представлять самого себя, если перед ним стоит \. Все символы, заключенные между кавычками ' и ', представляют самих себя. Между двойными кавычками (") выполняются подстановки команд (см п. 2.2) и параметров (см. п. 2.3), а символы \, `," и $ могут экранироваться предшествующим символом \.

После всех подстановок в каждом слове команды ищутся символы *,?, и [. Если находится хотя бы один из них, то это слово рассматривается как шаблон имен файлов и заменяется именами файлов, удовлетворяющих данному шаблону (в алфавитном порядке). Если ни одно имя файла не удовлетворяет шаблону, то он остается неизменным. Значения указанных символов:

*

любая строка, включая и пустую

?

один любой символ

[...]

любой из указанных между ними символов. Пара символов, разделенных знаком -, означает любой символ, который находится между ними, включая и их самих. Если первым символом после "[" идет "!", то указанные символы не должны входить в имя файла

Пример:

·  echo a* - перечисляет имена всех файлов текущего каталога, начинающихся на а;

·  sort a?? - cортирует все файлы, имя которых начинается на а и состоит из 3-х букв;

·  cat [a-d]* - выдаст файлы, которые начинаются с "a", "b", "c", "d". Аналогичный эффект

·  дадут и команды "cat [abcd]*" и "cat [bdac]*".

2.5. Командные файлы (script'ы)

Для того, чтобы текстовый файл можно было использовать как команду, существует несколько возможностей.

Пусть с помощью редактора создан файл с именем "cmd", содержащий одну строку следующего вида:

date; pwd; ls

Можно вызвать shell как команду (!), обозначаемую "sh", и передать ей файл "cmd", как аргумент или как перенаправленный вход, т. е.

$ sh cmd или $ sh <cmd

В результате выполнения любой из этих команд будет выдана дата, затем имя текущего каталога, а потом содержимое каталога.

Более интересный и удобный вариант работы с командным файлом - это превратить его в выполняемый, т. е. просто сделать его командой, что достигается изменением кода защиты. Для этого надо разрешить выполнение этого файла.

Например,

chmod 711 cmd

сделает код защиты "rwx__x__x". Тогда простой вызов

cmd

приведет к выполнению тех же трех команд.

Результат будет тот же, если файл с содержимым

date; pwd; ls

представлен в виде:

date

pwd

ls

так как переход на другую строку также является разделителем в последовательности команд.

Таким образом, выполняемыми файлами могут быть не только файлы, полученные в результате компиляции и сборки, но и файлы, написанные на языке shell. Их выполнение происходит в режиме интерпретации с помощью shell-интерпретатора

Еще раз отметим, что shell-интерпретатор, это всего лишь одна из сотен команд ОС UNIX, имеющая равные с прочими привилегии.

2.6. Рекурсивные скрипты

Shell позволяет использовать рекурсии в виде рекурсивных скриптов. Рекурсия - это вызов программой самой себя.

Пример:

Удалить файлы из каталога и всех его подкаталогов.

###

# my: Удаление файлов из каталога и всех его подкаталогов

cd $1

echo "directory $1"

set *

for i in *

do

if test - d $i

then

my $i

else

echo $i

while read a || exit

do

case $a in

n*)

break

;;

" ")

rm $i

break

;;

esac

done

fi

done

3. Синтаксис языка shell

3.1. Комментарии

Строки, начинающиеся с #, трактуются как комментарии.

3.2. Подстановка результатов выполнения команд

Выражения можно заключать в обратные кавычки (`). Такие выражения вычисляются в месте использования. Они могут быть, например, частью строк. Пример. Пусть параметром макрокоманды является имя файла с расширением. for. Требуется удалить одноименный файл с расширением. err.

name=`ena - n $1`

rm - f ${name}.err

Значение, полученное в результате выполнения команды

ena - n $1

присваивается переменной name. Фигурные скобки использованы для выделения аргумента операции перехода от имени к значению. Без них. err приклеилась бы к имени.

3.3. Переменные и подстановка их значений

Все переменные в языке shell - текстовые. Их имена должны начинаться с буквы и состоять из латинских букв, цифр и знака подчеркивания (_). Чтобы воспользоваться значением переменной, надо перед ней поставить символ $. Использование значения переменной называется подстановкой.

Различается два класса переменных: позиционные и с именем. Позиционные переменные - это аргументы командных файлов, их именами служат цифры: $0 - имя команды, $1 - первый аргумент и т. д. Значения позиционным переменным могут быть присвоены и командой set (см. Специальные команды). Пример. После вызова программы на shellе, хранящейся в файле ficofl:

ficofl - d / \*.for

значением $0 будет ficofl, $1 - - d, $2 - /, $3 - *.for, значения остальных позиционных переменных будут пустыми строками. Заметим, что если бы символ * при вызове ficofl не был экранирован, в качестве аргументов передались бы имена всех фортранных файлов текущей директории.

Еще две переменные хранят командную строку за исключением имени команды: $@ эквивалентно $1 $2 ..., а $* - "$1 $2 ...". Начальные значения переменным с именем могут быть установлены следующим образом:

<имя>=<значение> [ <имя>=<значение> ] ...

Не может быть одновременно функции (см. Управляющие конструкции) и переменной с одинаковыми именами. Для подстановки значений переменных возможны также следующие конструкции:

${<переменная>}

если значение <переменной> определено, то оно подставляется. Скобки применяются лишь если за <переменной> следует символ, который без скобок приклеится к имени.

${<переменная>:-<слово>}

если <переменная> определена и не является пустой строкой, то подставляется ее значение; иначе подставляется <слово>.

${<переменная>:=<слово>}

если <переменная> не определена или является пустой строкой, ей присваивается значение <слово>; после этого подставляется ее значение.

${<переменная>:?<слово>}

если <переменная> определена и не является пустой строкой, то подставляется ее значение; иначе на стандартный вывод выводится <слово> и выполнение shellа завершается. Если <слово> опущено, то выдается сообщение "parameter null or not set".

${<переменная>:+<слово>}

если <переменная> определена и не является пустой строкой, то подставляется <слово>; иначе подставляется пустая строка.

Пример: если переменная d не определена или является пустой строкой, то выполняется команда pwd

echo ${d:-`pwd`}

Следующие переменные автоматически устанавливаются shell'ом:

#

количество позиционных параметров (десятичное)

-

флаги, указанные при запуске shellа или командой set

?

десятичное значение, возвращенное предыдущей синхронно выполненной командой

$

номер текущего процесса

!

номер последнего асинхронного процесса

@

эквивалентно $1 $2 $3 ...

*

эквивалентно "$1 $2 $3 ..."

Напомним: чтобы получить значения этих переменных, перед ними нужно поставить знак $. Пример: выдать номер текущего процесса:

echo $$

3.4. Специальные переменные

Shell'ом используются следующие специальные переменные:

HOME

директория, в которую пользователь попадает при входе в систему или при выполнении команды cd без аргументов

PATH

список полных имен каталогов, в которых ищется файл при указании его неполного имени.

PS1

основная строка приглашения (по умолчанию $)

PS2

дополнительная строка приглашения (по умолчанию >); в интерактивном режиме перед вводом команды shell'ом выводится основная строка приглашения.
Если нажата клавиша new_line, но для завершения команды требуется дальнейший ввод, то выводится дополнительная строка приглашения

IFS

последовательность символов, являющихся разделителями в командной строке (по умолчанию это <пробел>, <табуляция> и <возврат_каретки>)

4. Управляющие конструкции

Простая команда - это последовательность слов, разделенная пробелами. Первое слово является именем команды, которая будет выполняться, а остальные будут переданы ей как аргументы. Имя команды передается ей как аргумент номер 0 (т. е. имя команды является значением $0). Значение, возвращаемое простой командой - это ее статус завершения, если она завершилась нормально, или (восьмеричное) 200+статус, если она завершилась аварийно.

Список - это последовательность одного или нескольких конвейеров, разделенных символами ;, &, && или || и быть может заканчивающаяся символом ; или &. Из четырех указанных операций ; и & имеют равные приоритеты, меньшие, чем у && и ||. Приоритеты последних также равны между собой. Символ ; означает, что конвейеры будут выполняться последовательно, а & - параллельно. Операция && (||) означает, что список, следующий за ней будет выполняться лишь в том случае, если код завершения предыдущего конвейера нулевой (ненулевой).

Команда - это либо простая команда, либо одна из управляющих конструкций. Кодом завершения команды является код завершения ее последней простой команды.

4.1 Цикл FOR

for <переменная> [ in <набор> ]

do

<список>

done

Если часть in <набор> опущена, то это означает in "$@" ( то есть in $1 $2 ... $n).

Пример 1.

Вывести на экран все фортранные файлы текущей библиотеки:

for f in *.for

do

cat $f

done

Пример 2.

Пусть команда "lsort" представлена командным файлом

for i in f1 f2 f3

do

proc-sort $i

done

В этом примере имя "i" играет роль параметра цикла. Это имя можно рассматривать как shell-переменную, которой последовательно присваиваются перечисленные значения (i=f1, i=f2, i=f3), и выполняется в цикле команда "procsort".

Пример 3.

Часто используется форма "for i in *", означающая "для всех файлов текущего каталога".

Пусть "proc-sort" в свою очередь представляется командным файлом

cat $1 | sort | tee /dev/lp > ${1}_sorted

т. е. последовательно сортируются указанные файлы, результаты сортировки выводятся на печать ("/dev/lp") и направляются в файлы f1_sorted f2_sorted и f3_sorted

Можно сделать более универсальной команду "lsort", если не фиксировать перечень файлов в команде, а передавать произвольное их число параметрами.

Тогда головная программа будет следующей:

for i

do

proc-sort $i

done

Здесь отсутствие после "i" служебного слова "in" с перечислением имен говорит о том, что список поступает через параметры команды. Результат предыдущего примера можно получить, набрав

lsort f1 f2 f3

Пример 4.

###

# subdir: Выдает имена всех поддиректориев

# директория с именем $dir

for i in $dir/*

do

if [ - d $i ]

then echo $i

fi

done

Пример 5.

Следующий расчет иллюстрирует полезный, хотя и с долей трюкачества, способ повторения одних и тех же действий несколько раз. Переменная "i" принимает здесь пять значений: 1, 2, 3, 4, 5, но внутри цикла эта переменная отсутствует и поэтому ее значение никакой роли не играет и ни чего не меняет. С таким же успехом переменная "i" могла принимать значения, скажем ф о к у с, а в результате точно также было бы пять раз повторено одно и то же вычисление содержимого цикла без изменений.

###

# print-5: Организации пятикратного выполнения команды

for i in

do

cat file-22 > /dev/lp

done

Пример 6.

Расчет "print-n" иллюстрирует еще одну полезную возможность в использовании цикла "for". Здесь, после "for i...", отсутствуют "in..." и перечень имен, т. е. перечнем имен для "i" становится перечень параметров, а следовательно количество печатаемых экземпляров можно менять.

###

# print-n: Задание числа копий

# через параметры

for i

do

cat file-22 > /dev/lp

done

Смысл не изменится, если первую строку расчета записать как

for i in $*

поскольку значение "$*" - есть список значений параметров.

Отметим различие в специальных переменных "$*" и "$@", представляющих перечень параметров. Первый представляет параметры, как строку, а второй, как совокупность слов.

Пример 7.

Пусть командный файл "cmp" имеет вид:

for i in "$*"

do

echo $i

done

echo

for i in "$@"

do

echo $i

done

При вызове

cmp aa bb cc

на экран будет выведено

aa bb cc

aa

bb

cc

4.2 Оператор выбора

case $<переменная> in

<шаблон> | <шаблон>... ) <список> ;;

. . .

esac

Оператор выбора выполняет <список>, соответствующий первому <шаблону>, которому удовлетворяет <переменная>. Форма шаблона та же, что и используемая для генерации имен файлов. Часть | шаблон... может отсутствовать.

Пример 1.

Определить флаги и откомпилировать все указанные файлы.

# инициализировать флаг

flag=

# повторять для каждого аргумента

for a

do

case $a in

# объединить флаги, разделив их пробелами

-[ocSO]) flag=$flag' ' $a ;;

-*) echo 'unknown flag $a' ;;

# компилировать каждый исходный файл и сбросить флаги

*.c) cc $flag $a; flag= ;;

*.s) as $flag $a; flag= ;;

*.f) f77 $flag $a; flag= ;;

# неверный аргумент

*) echo 'unexpected argument $a' ;;

esac

done

Пример 2.

echo - n " А какую оценку получил на экзамене?: "

read z

case $z in

5) echo Молодец! ;;

4) echo Все равно молодец! ;;

3) echo Все равно! ;;

2) echo Все! ;;

*) echo! ;;

esac

Непривычно выглядят в конце строк выбора ";;", но написать здесь ";" было бы ошибкой. Для каждой альтернативы может быть выполнено несколько команд. Если эти команды будут записаны в одну строку, то символ ";" будет использоваться как разделитель команд.

Обычно последняя строка выбора имеет шаблон "*", что в структуре "case" означает "любое значение". Эта строка выбирается, если не произошло совпадение значения переменной (здесь $z) ни с одним из ранее записанных шаблонов, ограниченных скобкой ")". Значения просматриваются в порядке записи.

Пример 3.

###

# case-3: Справочник.

# Для различных фирм по имени выдается

# название холдинга, в который она входит

case $1 in

ONE|TWO|THREE) echo Холдинг: ZERO ;;

MMM|WWW) echo Холдинг: Not-Net ;;

Hi|Hello|Howdoing) echo Холдинг: Привет! ;;

*) echo Нет такой фирмы ;;

esac

При вызове "case-3 Hello" на экран будет выведено:

Холдинг: Привет!

А при вызове "case-3 HELLO" на экран будет выведено:

Нет такой фирмы

Пример 4.

Коль скоро слово "case" переводится как "выбор", то это как бы намек на то, что можно эту структуру использовать для реализации простейших меню.

###

# case-4: Реализация меню с помощью команды "case"

echo "Назовите файл, а затем (через пробел)

наберите цифру, соответствующую требуемой

обработке:

1 - отсортировать

2 - выдать на экран

3 - определить число строк "

read x y # x - имя файла, y - что сделать

case $y in

1) sort < $x ;;

2) cat < $x ;;

3) wc - l < $x ;;

*) echo "

Мы не знаем

такой команды! " ;;

esac

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

Пример 5.

Напишем команду "case-5", которая добавляет информацию к файлу, указанного первым параметром (если параметр один), со стандартного входа, либо (если 2 параметра) из файла, указанного в качестве первого параметра:

###

# case-5: Добавление в файл.

# Использование стандартной переменной.

# "$#" - число параметров при вводе расчета

# ">>" - перенаправление с добавлением в файл

case $# in

1) cat >> $1 ;;

2) cat >> $2 < $1 ;;

*) echo "Формат: case-4 [откуда] куда" ;;

esac

"$1" (при "$#=1") - это имя файла, в который происходит добавление со стандартного входа.

"$1" и "$2" (при $#=2) - это имена файлов, из которого ("$1") и в который ("$2") добавлять.

Во всех других случаях (*) выдается сообщение о том, каким должен быть правильный формат команды.

4.3. Условный оператор.

if <список1>

then

<список2>

[ elif <список3>

then

<список4> ]

. . .

[ else

<список5> ]

fi

Выполняется <список1> и, если код его завершения 0, то выполняется <список2>, иначе - <список3> и, если и его код завершения 0, то выполняется <список4>. Если же это не так, то выполняется <список5>. Части elif и else могут отсутствовать.

Примеры.

Пусть написан расчет "if-1"

if [ $1 - gt $2 ]

then pwd

else echo $0 : Hello!

Fi

Тогда вызов расчета

if-1 12 11

даст

/home/sae/STUDY/SHELL

а

if-1 12 13

даст

if-1 : Hello!

Возможно использовать в условии то свойство shell, что команды могут выдавать различный код завершения. Это напоминает приемы программирования на Си. Пусть расчет "if-2" будет

if a=`expr "$1" : "$2"`

then echo then a=$a code=$?

else echo else a=$a code=$?

Fi

тогда вызов

if-2 by by

даст

then a=2 code=0

а

if-2 by be

даст

else a=0 code=1

Еще пример на вложенность

###

# if-3: Оценка достижений

echo - n " А какую оценку получил на экзамене?: "

read z

if [ $z = 5 ]

then echo Молодец!

elif [ $z = 4 ]

then echo Все равно молодец!

elif [ $z = 3 ]

then echo Все равно!

elif [ $z = 2 ]

then echo Все!

else echo!

fi

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

4.4. Цикл WHILE

while <список1>

do

<список2>

done

До тех пор, пока код завершения последней команды <списка1> есть 0, выполняются команды <списка2>. При замене служебного слова while на until условие выхода из цикла меняется на противоположное.

В качестве одной из команд <списка1> может быть команда true (false). По этой команде не выполняется никаких действий, а код завершения устанавливается 0 (-1). Эти команды применяются для организации бесконечных циклов. Выход из такого цикла можно осуществить лишь по команде break (см. Специальные команды).

Пример 1.

###

# print-50: Структура "while"

# Расчет позволяет напечатать 50

# экземпляров файла "file-22"

n=0

while [ $n - lt 50 ] # пока n < 50

do

n=`expr $n + 1`

cat file-22 > /dev/lp

done

Обратим внимание на то, что переменной "n" вначале присваивается значение 0, а не пустая строка, так как команда "expr" работает с shell-переменными как с целыми числами, а не как со строками.

n=`expr $n + 1`

т. е. при каждом выполнении значение "n" увеличивается на 1.

Пример 2.

Как и вообще в жизни, можно реализовать то же самое и сложнее. Расчет "рr-br" приведен для иллюстрации бесконечного цикла и использования команды "break", которая обеспечивает прекращение цикла.

###

# рr-br: Структура "while" c "break"

# Расчет позволяет напечатать 50

# экземпляров файла "file-22"

n=0

while true

do

if [ $n - lt 50 ] # если n < 50

then n=`expr $n + 1`

else break

fi

cat file-22 > /dev/lp

done

4.5 Функции


<имя> () {

<список>;

}


Определяется функция с именем <имя>. Тело функции - <список>, заключенный между { и }.

Пример.

Вызов на выполнение файла "fun"

echo $$

fn() # описание функции

{

echo xx=$xx

echo $#

echo $0: $$ $1 $2

xx=yy ; echo xx=$xx

return 5

}

xx=xx ; echo xx=$xx

fn a b # вызов функции "fn" с параметрами

echo $?

echo xx=$xx

содержащего описание и вызов функции "fn", выдаст на экран:

749

xx=xx

xx=xx

2

fun: 749 a b

xx=yy

5

xx=yy

4.6. Зарезервированные слова

Следующие слова являются зарезервированными:

if then else elif fi

case in esac { }

for while until do done

4.7. Специальные команды

Как правило, для выполнения каждой команды shell порождает отдельный процесс. Специальные команды отличаются тем, что они встроены в shell и выполняются в рамках текущего процесса.

:

Пустая команда. Возвращает нулевой код завершения.

. file

Shell читает и выполняет команды из файла file, затем завершается; при поиске file используется список поиска $PATH.

break [n]

Выход из внутреннего for или while цикла; если указано n, то выход из n внутренних циклов.

continue [n]

Перейти к следующей итерации внутреннего for или while цикла; если указано n, то переход к следующей итерации n-ого цикла.

cd [ <аргумент> ]

Сменить текущую директорию на директорию <аргумент>. По умолчанию используется значение HOME.

echo [ <арг> ... ]

Выводит свои аргументы в стандартный вывод, разделяя их пробелами.

eval [ <арг> ... ]

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

exec [ <арг> ... ]

Аргументы рассматриваются как команды shell'а и тут же выполняются, но при этом не создается нового процесса. В качестве аргументов могут быть указаны направления ввода-вывода и, если нет никаких других аргументов, то будет изменено лишь направление ввода-вывода текущей программы.

exit [ n ]

Завершение выполнения shell'а с кодом завершения n. Если n опущено, то кодом завершения будет код завершения последней выполненной команды (конец файла также приводит к завершению выполнения).

export [ <переменная> ... ]

Данные переменные отмечаются для автоматического экспорта в окружение (см. Окружение) выполняемых команд. Если аргументы не указаны, то выводится список всех экспортируемых переменных. Имена функций не могут экспортироваться.

hash [ - r ] [ <команда> ... ]

Для каждой из указанных команд определяется и запоминается путь поиска. Опция - r удаляет все запомненные данные. Если не указан ни один аргумент, то выводится информация о запомненных командах: hits - количество обращений shell'а к данной команде; cost - объем работы для обнаружения команды в списке поиска; command - полное имя команды. В некоторых ситуациях происходит перевычисление запомненных данных, что отмечается значком * в поле hits.

pwd

Выводит имя текущей директории.

read [ <переменная> ... ]

Читается из стандартного ввода одна строка; первое ее слово присваивается первой переменной, второе - второй и т. д., причем все оставшиеся слова присваиваются последней переменной.

readonly [ <переменная> ... ]

Запрещается изменение значений указанных переменных. Если аргумент не указан, то выводится информация обо всех переменных типа readonly.

return [ n ]

Выход из функции с кодом завершения n. Если n опущено, то кодом завершения будет код завершения последней выполненной команды.

set [ --aefkntuvx [ <арг> ... ] ]

Команда устанавливает следующие режимы:

-a

отметить переменные, которые были изменены или созданы, как переменные окружения (см. Окружение)

-e

если код завершения команды ненулевой, то немедленно завершить выполнение shell'а

-f

запретить генерацию имен файлов

-k

все переменные с именем помещаются в окружение команды, а не только те, что предшествуют имени команды (см. Окружение)

-n

читать команды, но не выполнять их

-t

завершение shell'а после ввода и выполнения одной команды

-u

при подстановке рассматривать неустановленные переменные как ошибки

-v

вывести вводимые строки сразу после их ввода

-x

вывести команды и их аргументы перед их выполнением

--

не изменяет флаги, полезен для присваивания позиционным переменным новых значений.

При указании + вместо - каждый из флагов устанавливает противоположный режим. Набор текущих флагов есть значение переменной $-. <арг> - это значения, которые будут присвоены позиционным переменным $1, $2 и т. д. Если все аргументы опущены, выводятся значения всех переменных.

shift [ n ]

Позиционные переменные, начиная с $(n+1), переименовываются в $1 и т. д. По умолчанию n=1.

test

вычисляет условные выражения (см. Дополнительные сведения. Test )

trap [ <арг> ] [ n ] ...

Команда <арг> будет выполнена, когда shell получит сигнал n (см. Сигналы). (Надо заметить, что <арг> проверяется при установке прерывания и при получении сигнала). Команды выполняются по порядку номеров сигналов. Любая попытка установить сигнал, игнорируемый данным процессом, не обрабатывается. Попытка прерывания по сигналу 11 (segmentation violation) приводит к ошибке. Если <арг> опущен, то все прерывания устанавливаются в их начальные значения. Если <арг> есть пустая строка, то этот сигнал игнорируется shell'ом и вызываемыми им программами. Если n=0, то <арг> выполняется при выходе из shell'а. Trap без аргументов выводит список команд, связанных с каждым сигналом.

type [ <имя> ... ]

Для каждого имени показывает, как оно будет интерпретироваться при использовании в качестве имени команды: как внутренняя команда shell'а, как имя файла или же такого файла нет вообще.

ulimit [ - f ] [ n ]

Устанавливает размер файла в n блоков; - f - устанавливает размер файла, который может быть записан процессом-потомком (читать можно любые файлы). Без аргументов - выводит текущий размер.

umask [ nnn ]

Пользовательская маска создания файлов изменяется на nnn. Если nnn опущено, то выводится текущее значение маски. Пример: после команды umask 755 будут создаваться файлы, которые владелец сможет читать, писать и выполнять, а все остальные - только читать и выполнять.

unset [ <имя> ... ]

Для каждого имени удаляет соответствующую переменную или функцию. Переменные PATH, PS1, PS2 и IFS не могут быть удалены.

wait [ n ]

Ждет завершения указанного процесса и выводит код его завершения. Если n не указано, то ожидается завершения всех активных процессов-потомков и возвращается код завершения 0.

Примеры:

·  for i in *

·  do

·  if test - d $i

·  then

·  break #если директория, то выходим из цикла

·  else

·  echo $i #иначе печатаем имя файла и начинаем следующую итерацию цикла

·  continue

·  fi

·  done

·  сменить текущую директорию на /usr/X11

·  $ cd /usr/X11

·  вывести на стандартные выход имена всех файлов текущей директории

·  $ echo *

·  завершить по условию работу программы и возвратить код -1

·  & if <условие>

·  > then exit -1

·  >...

·  экспортировать переменные var1 и var2 в окружение

·  $ export var1 var2

·  запомнить путь поиска команды sed

·  $ hash sed

·  записать имя текущей директории в файл dir

·  $ pwd > dir

·  прочитать из стандартного ввода значение переменной tr1

·  $ read tr1

·  просмотреть список переменных с аттрибутом "только для чтения" и установить этот аттрибут

·  для переменной vvreadonly

·  $ readonly; readonly vvreadonly

·  вывести на экран все переменные окружения

·  $ set

·  проверить существует ли такая команда или файл sqwreg (т. е. как shell её интерпретирует)

·  $ type sqwreg

·  задать максимальный размер файла, который может создать процесс/поток, равный 10 блоков

·  $ ulimit 10

·  просмотреть текущее значение маски

·  $ umask

·  удалить из окружения переменную var1

·  $ uset var1

·  ожидать выполнение процесса 711

·  wait 711

5. Выполнение shell-программ

5.1. Запуск shell'а

Программа, интерпретирующая shell-программы, находится в файле /bin/sh. При запуске ее первый аргумент является именем shell-программы, остальные передаются как позициональные параметры. Если файл, содержащий shell-программу, имеет право выполнения (x), то достаточно указания лишь его имени. Например, следующие две команды операционной системы эквивалентны (если файл ficofl обладает указанным правом и на самом деле содержит shell-программу):

sh ficofl - d. g\*

и

ficofl - d. g\*

5.2. Выполнение

При выполнении shell-программ выполняются все подстановки. Если имя команды совпадает с именем специальной команды, то она выполнается в рамках текущего процесса. Так же выполняются и определенные пользователем функции. Если имя команды не совпадает ни с именем специальной команды, ни с именем функции, то порождается новый процесс и осуществляется попытка выполнить указанную команду.

Переменная PATH определяет путь поиска директории, содержащей данную команду. По умолчанию это

::/bin:/usr/ bin:/util:/dss/rk

Директории поиска разделяются двоеточиями; :: означает текущую директорию. Если имя команды содержит символ /, значение $PATH не используется: имена, начинающиеся с / ищутся от корня, остальные - от текущей директории. Положение найденной команды запоминается shellом и может быть опрошено командой hash.

5.3. Подстановки shell-интерпретатора

Перед началом непосредственной интерпретации и выполнением команд, содержащихся в командных файлах, shell выполняет различные виды подстановок:

ПОДСТАНОВКА РЕЗУЛЬТАТОВ. Выполняются все команды, заключенные в обратные кавычки, и на их место подставляется результат. ПОДСТАНОВКА ЗНАЧЕНИЙ ПАРАМЕТРОВ И ПЕРЕМЕННЫХ. То есть слова, начинающиеся на "$", заменяются соответствующими значениями переменных и параметров. ИНТЕРПРЕТАЦИЯ ПРОБЕЛОВ. Заэкранированные пробелы игнорируются. ГЕНЕРАЦИЯ ИМЕН ФАЙЛОВ. Проверяются слова на наличие в них спецсимволов ("*", "?","[]") и выполняются соответствующие генерации.

5.4. Окружение

Окружение - это набор пар имя-значение, которые передаются выполняемой программе. Shell взаимодействует с окружением несколькими способами. При запуске shell создает переменную для каждой указанной пары, придавая ей соответствующее значение. Если вы измените значение какой-либо из этих переменных или создадите новую переменную, то это не окажет никакого влияния на окружение, если не будет использована команда export для связи переменной shell'а с окружением (см. также set - a). Переменная может быть удалена из окружения командой unset (см.). Таким образом, окружение каждой из выполняемых shell'ом команд формируется из всех неизмененных пар имя-значение, первоначально полученных shell'ом, минус пары, удаленные командой unset, плюс все модифицированные и измененные пары, которые для этого должны быть указаны в команде export.

Окружение простых команд может быть сформировано указанием перед ней одного или нескольких присваиваний переменным. Так,

TERM=d460 <команда>

и

(export TERM; TERM=d460; <команда>)

эквивалентны. Переменные, участвующие в таких присваиваниях, назовем ключевыми параметрами.

Если установлен флаг - k (см. set), то все ключевые параметры помещаются в окружение команды, даже если они записаны после команды.

5.5. Сигналы

UNIX'ом поддерживаются следующие сигналы:

SIGHUP

- 1 -

отменить (hangup)

SIGINT

- 2 -

прерывание (interrupt)

SIGQUIT

- 3 -

нестандартный выход (quit)

SIGILL

- 4 -

неверная команда (illegal instruction)

SIGTRAP

- 5 -

ловушка (trace trap)

SIGFPE

- 8 -

исключительная ситуация при выполнении операций с плавающей запятой (floating-point exception)

SIGKILL

- 9 -

уничтожение процесса (kill)

SIGBUS

- 10 -

ошибка шины (bus error)

SIGSEGV

- 11 -

нарушение сегментации (segmentation violation)

SIGSYS

- 12 -

неверный системный вызов (bad argument to system call)

SIGPIPE

- 13 -

запись в канал без чтения из него (write on a pipe with no one to read it)

SIGALRM

- 14 -

будильник (alarm clock)

SIGTERM

- 15 -

программное завершение процесса (software termination signal)

Сигналы SIGINT и SIGQUIT игнорируются, если команда была запущена асинхронно. Иначе сигналы обрабатываются так же, как в процессе-предке, за исключением сигнала SIGSEGV (см. также Специальные команды. Trap).

5.6. Замечания

При выполнении команд запоминается их местонахождение. Поэтому при создании команды с тем же именем, но находящейся в другой директории, все равно будет выполняться старая команда (если вызов происходит по короткому имени). Для исправления ситуации воспользуйтесь командой hash с ключом - r (см. Специальные команды).

Если вы переименовали текущую или вышележащую директорию, то команда pwd может давать неверную информацию. Для исправления ситуации воспользуйтесь командой cd с полным именем директории.

6. Дополнительные сведения

6.1. Команда test

Команда test проверяет выполнение некоторого условия. С использованием этой (встроенной) команды формируются операторы выбора и цикла языка shell. (См. Оператор выбора, Условный оператор, Цикл WHILE)

Два возможных формата команды:

test условие

или

[ условие ]

мы будем пользоваться вторым вариантом, т. е. вместо того, чтобы писать перед условием слово "test", будем заключать условие в скобки, что более привычно для программистов.

На самом деле shell будет распознавать эту команду по открывающей скобке "[", как слову(!), соответствующему команде "test". Уже этого достаточно, чтобы предупредить о распространенной ошибке начинающих: Между скобками и содержащимся в них условием обязательно должны быть пробелы.

Пробелы должны быть и между значениями и символом сравнения или операции (как, кстати, и в команде "expr"). Не путать с противоположным требованием для присваивания значений переменным.

В shell используются условия различных "типов".

УСЛОВИЯ ПРОВЕРКИ ФАЙЛОВ:

-f file

файл "file" является обычным файлом;

-d file

файл "file" - каталог;

-с file

файл "file" - специальный файл;

-r file

имеется разрешение на чтение файла "file";

-w file

имеется разрешение на запись в файл "file";

-s file

файл "file" не пустой.

Примеры. Вводя с клавиатуры командные строки в первом случае получим подтверждение (код завершения "0"), а во втором - опровержение (код завершения "1"). "specific" - имя существующего файла.

[ - f specific ] ; echo $?

0

[ - d specific ] ; echo $?

1

УСЛОВИЯ ПРОВЕРКИ СТРОК:

str1 = str2

строки "str1" и "str2" совпадают;

str1 != str2

строки "str1" и "str2" не совпадают;

-n str1

строка "str1" существует (непустая);

-z str1

строка "str1" не существует (пустая).

Примеры.

x="who is who"; export x; [ "who is who" = "$x" ]; echo $?

0

x=abc ; export x ; [ abc = "$x" ] ; echo $?

0

x=abc ; export x ; [ - n "$x" ] ; echo $?

0

x="" ; export x ; [ - n "$x" ] ; echo $?

1

Команда "test" дает значение "истина" (т. е. код завершения "0") и просто если в скобках стоит непустое слово.

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

true ; echo $?

0

false ; echo $?

1

УСЛОВИЯ СРАВНЕНИЯ ЦЕЛЫХ ЧИСЕЛ:

x - eq y

"x" равно "y",

x - ne y

"x" неравно "y",

x - gt y

"x" больше "y",

x - ge y

"x" больше или равно "y",

x - lt y

"x" меньше "y",

x - le y

"x" меньше или равно "y".

То есть в данном случае команда "test" воспринимает строки символов как целые (!) числа. Поэтому во всех остальных случаях "нулевому" значению соответствует пустая строка. В данном же случае, если надо обнулить переменную, скажем, "x", то это достигается присваиванием "x=0".

Примеры.

x=abc ; export x ; [ abc - eq "$x" ] ; echo $?

"[": integer expression expected before - eq

x=321 ; export x ; [ 321 - eq "$x" ] ; echo $?

0

x=3.21 ; export x ; [ 3.21 - eq "$x" ] ; echo $?

"[": integer expression expected before - eq

x=321 ; export x ; [ 123 - lt "$x" ] ; echo $?

0

СЛОЖНЫЕ УСЛОВИЯ:

Реализуются с помощью типовых логических операций:

!

(not) инвертирует значение кода завершения.

-o

(or) соответствует логическому "ИЛИ".

-a

(and) соответствует логическому "И".

ПРЕДУПРЕЖДЕНИЕ. Не забывайте о пробелах.

Примеры.

[ ! privet ] ; echo $?

1

x=privet; export x; [ "$x" - a - f specific ] ; echo $?

0

x="";export x; [ "$x" - a - f specific ] ; echo $?

1

x="";export x; [ "$x" - a - f specific - o privet ] ; echo $?

0

x="";export x; [ "$x" - a - f specific - o! privet ] ; echo $?

1

6.2. Команда expr

Команда expr применяется для вычисления выражений. Результат выводится на стандартный вывод. Операнды выражения должны быть разделены пробелами. Метасимволы должны быть экранированы. Надо заметить, что 0 возвращается в качестве числа, а не для индикации пустой строки. Строки, содержащие пробелы или другие специальные символы, должны быть заключены в кавычки. Целые рассматриваются как 32-битные числа.

Ниже приведен список операторов в порядке возрастания приоритета, операции с равным приоритетом заключены в фигурные скобки. Перед символами, которые должны быть экранированы, стоит \.

<выр> \| <выр>

если первое <выр> не пустое и не нулевое, то возвращает его, иначе возвращает второе <выр>

<выр> \& <выр>

если оба <выр> не пустые и не нулевые, то возвращает первое <выр>, иначе возвращает 0

<выр> { =, \>, \>=, \<, \<=, != } <выр>

возвращает результат целочисленного сравнения если оба <выр> - целые; иначе возвращает результат лексического сравнения

<выр> { +, - } <выр>

сложение и вычитание целочисленных аргументов

<выр> { \*, /, % } <выр>

умножение, деление и получение остатка от деления целочисленных аргументов

<выр> : <выр>

оператор сопоставления : сопоставляет первый аргумент со вторым, который должен быть регулярным выражением. Обычно оператор сравнения возвращает число символов, удовлетворяющих образцу (0 при неудачном сравнении). Однако символы \( и \) могут применяться для выделения части первого аргумента.

Регулярное выражение строится следующим образом:

.

- обозначает любой символ

*

- обозначает предыдущий символ, повторенный несколько раз

[]

- обозначают любой один из указанных между ними символов; группа символов может обозначаться с помощью знака "-" (т. е. [0-9] эквивалентно []); если после [ стоит ^, то это эквивалентно любому символу, кроме указанных в скобках и <возврата_каретки>; для указания ] в качестве образца, надо поставить ее сразу за [ (т. е. []...]); . и * внутри квадратных скобок обозначают самих себя

Более подробная информация о регулярных выражениях находится по адресу www. asu. pstu. *****/unix/regular_expression.

Все остальные символы (и ^, если стоит не в квадратных скобках) обозначают самих себя. Для указания символов., *,[ и ] надо экранировать их (т. е. писать \., \*, \[, \]).

Примеры.

1.

a=`expr $a + 1`

- увеличение на 1 переменной a

2.

expr $a : '.*/\(.*\)' \| $a

- выделяет из имени файла короткое имя (т. е. из /usr/util/ena выделяется ena). Внимание, одиночный символ / будет воспринят как знак операции деления.

3.

expr $VAR : '.*'

- получение количества символов переменной VAR.

В качестве побочного эффекта expr возвращает следующие коды завершения:

0

- если выражение не нуль и не пустая строка

1

- если выражение нуль или пустая строка

2

- для некорректных выражений

Команда expr также выдает следующие сообщения об ошибках:

syntax error

- для ошибок в операторах или операндах

non-numeric argument

- для попыток применения арифметических операций к нечисловым строкам

Замечание.

Допустим, что мы хотим сравнить значение переменной a с каким-либо символом, имеющим для expr особый смысл, например, со знаком равенства. Пусть $a на самом деле является знаком равенства. Так как аргументы предварительно обрабатываются shell'ом, то команда

expr $a = '='

будет воспринята как

expr = = =

что синтаксически некорректно. В подобных случаях надо пользоваться таким приемом:

expr X$a = X=

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

7. Контрольные задания

Вопрос.

Ответ.

Вывести содержимое переменной PATH без перехода на новую строку

echo - n $PATH

C новой страницы выведите предложение, разделяя слова табуляцией

echo - e "\fслова\tиз\tкоторых\tcостоит\tпредложение"

Вывести значения переменных PS1 и PS2 в файл, разделив их обратным слэшем

echo - e "$PS1\\$PS2" > filename

Добавить строку "Hello, World!" в файл

echo "Hello, World!" >> filename

Получить эхо имён файлов по одному в строке

for i in *
do
echo $i
done

Посылка письма адресатам из списка в файле

mail `cat mailinglist` < letter

Удалить все файлы, оканчивающиеся на. bak

rm *.bak

Вывести через пять минут сообщение о том, что чай готов. Процесс запустить в фоновом режиме.

(sleep 300; echo Чай готов) &

Удалить из текущего каталога и его подкаталогов все файлы нулевого размера, запрашивая подтверждение

find. - size 0c - ok rm {} ';'

Закройте свой домашний каталог (в директории home) для всех пользователей кроме себя

chmod o-xw /home/alex

Вывести последние 100 строк файла с сортировкой и с возможностью постепенного просмотра

tail -100 filename | sort | more

Написать фрагмет программы на shell, который при отсутствии почты, переадресовывает всю почту на другой адресат, например alex.

if [mail - e - eq 0]; then mail - F "alex"; fi.

Выяснить, работает ли mary в системе

who | grep Mary

Выполнить задание через неделю в 6 часов вечера

at 6pm today+week