Реферат: Интерпретатор командного языка shell
Интерпретатор командного языка shell
1. Основные понятия языка shell
1.1. Ввод-вывод
Три направления ввода-вывода являются выделенными - стандартный ввод, стандартный вывод и стандартный протокол. Как правило, команды берут исходные
данные из стандартного ввода и помещают результаты в стандартный вывод.
Стандартные ввод, вывод и протокол можно переназначить. Обозначение
< <имя файла> служит для переназначения стандартного ввода (дескриптор файла 0),
> <имя файла> для стандартного вывода (дескриптор файла 1);
<< <строка> ввод происходит со стандартного ввода, пока не встретится указанная
<строка> или конец файла,
>> <имя файла> для стандартного вывода; если файл существует, то выводимая информация
добавляется к конец этого файла,
<& <цифра> в качестве стандартного ввода об(r)является файл, ассоциированный с
дескриптором <цифра>; аналогично для стандартного вывода
>& <цифра> <&- и >&-
закрывают соответственно стандартный ввод и вывод.
Если любой из этих конструкций предшествует цифра, то с указанным файлом будет ассоциирован дескриптор, равный указанной цифре, вместо 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 - - < 1.2. Синхронное и асинхронное выполнение команд
Обычно shell ждет завершения выполнения команды. Однако имеется возможность запустить задачу в асинхронном режиме, т.е. без ожидания ее завершения. Для
этого после команды (после всех ее аргументов и указаний о переназначении ввода-вывода) надо поставить знак &. При этом по умолчанию стандартный ввод
команды назначается на пустой файл /dev/null.
Пример: создать файл primer можно по команде
echo > primer Еще пример: запустить программу prog в асинхронном режиме, чтобы не надо
было дожидаться его завершения, засечь время выполнения, результаты программы направить в файл prog.res, данные о времени выполнения - в файл prog.tim.
time prog > prog.res 2> prog.tim & 1.3. Конвейер
Конвейер - последовательность команд, разделенных знаком |. Если после конвейера стоит ; shell ждет его завершения. Если & - то не ждет. Роль ;
может играть конец строки. Смысл конвейера в том, что стандартный вывод одной команды замыкается на стандартный ввод другой. Пример конвейера - подсчитать
число об(r)ектных файлов в текущем каталоге.
ls *.o | wc -l 1.4. Метасимволы, генерация имен файлов
Метасимволы - символы, имеющие специальное значение для интерпретатора :
? * ; & ( ) | ^ < > <пробел> <табуляция> <возврат_каретки>
Однако каждый из этих символов может представлять самого себя, если перед ним стоит \. Все символы, заключенные между кавычками ' и ', представляют самих
себя. Между двойными кавычками (") выполняются подстановки команд (см п. 2.2) и параметров (см. п. 2.3), а символы \, `," и $ могут экранироваться
предшествующим символом \.
После всех подстановок в каждом слове команды ищутся символы *,?, и [. Если находится хотя бы один из них, то это слово рассматривается как шаблон имен
файлов и заменяется именами файлов, удовлетворяющих данному шаблону (в алфавитном порядке). Если ни одно имя файла не удовлетворяет шаблону, то он
остается неизменным. Значения указанных символов:
*
|
любая строка, включая и пустую
|
?
|
один любой символ
|
[...]
|
любой из указанных между ними символов. Пара символов, разделенных знаком -, означает любой символ,
который находится между ними, включая и их самих. Если первым символом после "[" идет "!", то указанные символы не должны входить в
имя файла
|
2.
Синтаксис языка shell
2.1. Комментарии
Строки, начинающиеся с #, трактуются как комментарии.
2.2. Подстановка результатов выполнения команд
Выражения можно заключать в обратные кавычки (`). Такие выражения вычисляются в месте использования. Они могут быть, например, частью строк.
Пример. Пусть параметром макрокоманды является имя файла с расширением .for. Требуется удалить одноименный файл с расширением .err.
name=`ena -n $1` rm -f ${name}.err Значение, полученное в результате выполнения команды
ena -n $1 присваивается переменной name. Фигурные скобки использованы для выделения
аргумента операции перехода от имени к значению. Без них .err приклеилась бы к имени.
2.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 $$ 2.4. Специальные переменные Shell'ом используются следующие специальные переменные:
HOME
|
директория, в которую пользователь попадает при входе в систему или при выполнении команды cd без
аргументов
|
PATH
|
список полных имен каталогов, в которых ищется файл при указании его неполного имени.
|
PS1
|
основная строка приглашения (по умолчанию $)
|
PS2
|
дополнительная строка приглашения (по умолчанию >); в интерактивном режиме перед вводом команды
shell'ом выводится основная строка приглашения. Если нажата клавиша new_line, но для завершения команды требуется дальнейший
ввод, то выводится дополнительная строка приглашения
|
IFS
|
последовательность символов, являющихся разделителями в командной строке (по умолчанию это
<пробел>, <табуляция> и <возврат_каретки>)
|
3.
Управляющие конструкции
Простая команда - это последовательность слов, разделенная пробелами. Первое слово является именем команды, которая будет выполняться, а остальные будут
переданы ей как аргументы. Имя команды передается ей как аргумент номер 0 (т.е. имя команды является значением $0). Значение, возвращаемое простой командой -
это ее статус завершения, если она завершилась нормально, или (восьмеричное) 200+статус, если она завершилась аварийно.
Список - это последовательность одного или нескольких конвейеров, разделенных символами ;, &, && или || и быть может заканчивающаяся
символом ; или &. Из четырех указанных операций ; и & имеют равные приоритеты, меньшие, чем у && и ||. Приоритеты последних также равны
между собой. Символ ; означает, что конвейеры будут выполняться последовательно, а & - параллельно. Операция && (||) означает, что
список, следующий за ней будет выполняться лишь в том случае, если код завершения предыдущего конвейера нулевой (ненулевой).
Команда - это либо простая команда, либо одна из управляющих конструкций. Кодом завершения команды является код завершения ее последней простой команды.
3.1. Цикл ДЛЯ
for <переменная> [ in <набор> ] do <список> done
Если часть in <набор> опущена, то это означает in "$@" ( то есть in $1 $2 ... $n). Пример. Вывести на экран все фортранные файлы текущей
библиотеки:
for f in *.for do cat $f done
3.2. Оператор выбора case $<переменная> in <шаблон> | <шаблон>... ) <список> ;; . . . esac
Оператор выбора выполняет <список>, соответствующий первому <шаблону>, которому удовлетворяет <переменная>. Форма шаблона та
же, что и используемая для генерации имен файлов. Часть | шаблон... может отсутствовать.
Пример. Определить флаги и откомпилировать все указанные файлы.
# инициализировать флаг flag= # повторять для каждого аргумента for a do case $a in # об(r)единить флаги, разделив их пробелами -[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
3.3. Условный оператор. if <список1> then <список2> [ elif <список3> then <список4> ] . . . [ else <список5> ] fi
Выполняется <список1> и, если код его завершения 0, то выполняется <список2>, иначе - <список3> и, если и его код завершения 0, то
выполняется <список4>. Если же это не так, то выполняется <список5>. Части elif и else могут отсутствовать.
3.4. Цикл ПОКА
while <список1> do <список2> done
До тех пор, пока код завершения последней команды <списка1> есть 0, выполняются команды <списка2>. При замене служебного слова while на until
условие выхода из цикла меняется на противоположное.
В качестве одной из команд <списка1> может быть команда true (false). По этой команде не выполняется никаких действий, а код завершения
устанавливается 0 (-1). Эти команды применяются для организации бесконечных циклов. Выход из такого цикла можно осуществить лишь по команде break (см.
Специальные команды).
3.5. Функции
<имя> () { <список>; }
Определяется функция с именем <имя>. Тело функции - <список>, заключенный между { и }.
3.6. Зарезервированные слова
Следующие слова являются зарезервированными:
if then else elif fi case in esac { } for while until do done
3.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.
|
4.
Выполнение shell-программ
4.1. Запуск shell'а
Программа, интерпретирующая shell-программы, находится в файле /bin/sh. При запуске ее первый аргумент является именем shell-программы, остальные передаются
как позициональные параметры. Если файл, содержащий shell-программу, имеет право выполнения (x), то достаточно указания лишь его имени. Например,
следующие две команды операционной системы эквивалентны (если файл ficofl обладает указанным правом и на самом деле содержит shell-программу):
sh ficofl -d . g\* и ficofl -d . g\*
4.2. Выполнение При выполнении shell-программ выполняются все подстановки. Если имя команды
совпадает с именем специальной команды, то она выполнается в рамках текущего процесса. Так же выполняются и определенные пользователем функции. Если имя
команды не совпадает ни с именем специальной команды, ни с именем функции, то порождается новый процесс и осуществляется попытка выполнить указанную команду.
Переменная PATH определяет путь поиска директории, содержащей данную команду. По умолчанию это
::/bin:/usr/ bin:/util:/dss/rk Директории поиска разделяются двоеточиями; :: означает текущую директорию.
Если имя команды содержит символ /, значение $PATH не используется: имена, начинающиеся с / ищутся от корня, остальные - от текущей директории. Положение
найденной команды запоминается shellом и может быть опрошено командой hash.
4.3. Окружение
Окружение - это набор пар имя-значение, которые передаются выполняемой программе. Shell взаимодействует с окружением несколькими способами. При
запуске shell создает переменную для каждой указанной пары, придавая ей соответствующее значение. Если вы измените значение какой-либо из этих
переменных или создадите новую переменную, то это не окажет никакого влияния на окружение, если не будет использована команда export для связи переменной
shell'а с окружением (см. также set -a). Переменная может быть удалена из окружения командой unset (см.). Таким образом, окружение каждой из выполняемых
shell'ом команд формируется из всех неизмененных пар имя-значение, первоначально полученных shell'ом, минус пары, удаленные командой unset, плюс
все модифицированные и измененные пары, которые для этого должны быть указаны в команде export.
Окружение простых команд может быть сформировано указанием перед ней одного или нескольких присваиваний переменным. Так,
TERM=d460 <команда> и (export TERM; TERM=d460; <команда>)
эквивалентны. Переменные, участвующие в таких присваиваниях, назовем ключевыми параметрами.
Если установлен флаг -k (см. set), то все ключевые параметры помещаются в окружение команды, даже если они записаны после команды.
4.4. Сигналы
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).
4.5. Замечания
При выполнении команд запоминается их местонахождение. Поэтому при создании команды с тем же именем, но находящейся в другой директории, все равно будет
выполняться старая команда (если вызов происходит по короткому имени). Для исправления ситуации воспользуйтесь командой hash с ключом -r (см. Специальные
команды).
Если вы переименовали текущую или вышележащую директорию, то команда pwd может давать неверную информацию. Для исправления ситуации воспользуйтесь
командой cd с полным именем директории.
5.
Дополнительные сведения
5.1. Команда test
Команда test применяется для проверки условия. Формат вызова:
test <выражение> или [ <выражение> ]
Команда test вычисляет <выражение> и, если его значение - истина, возвращает код завершения 0 (true); иначе - ненулевое значение (false).
Ненулевой код завершения возвращается и если опущены аргументы. <Выражение> может состоять из следующих примитивов:
-r файл
|
- истина, если файл существует и доступен для чтения
|
-w файл
|
- истина, если файл существует и доступен для записи
|
-x файл
|
- истина, если файл существует и является выполняемым
|
-f файл
|
- истина, если файл существует и является обычным файлом
|
-d файл
|
- истина, если файл существует и является директорией
|
-c файл
|
- истина, если файл существует и является специальным символьно-ориентированным файлом
|
-b файл
|
- истина, если файл существует и является специальным блок-ориентированным файлом
|
-p файл
|
- истина, если файл существует и является именованным каналом (pipe)
|
-s файл
|
- истина, если файл существует и имеет ненулевую длину
|
-t [ дескриптор файла ]
|
- истина, если открытый файл с указанным дескриптором (по умолчанию 1) существует и ассоциирован с
терминалом
|
-z s1
|
- истина, если длина строки s1 нулевая
|
-n s1
|
- истина, если длина строки s1 ненулевая
|
s1 = s2
|
- истина, если строки s1 и s2 совпадают
|
s1 != s2
|
- истина, если строки s1 и s2 не совпадают
|
s1
|
- истина, если s1 непустая строка
|
n1 -eq n2
|
- истина, если целые n1 и n2 алгебраически совпадают . На месте -eq могут быть также -ne, -gt, -ge,
-lt, -le
|
5.2. Команда expr
Команда expr применяется для вычисления выражений. Результат выводится на стандартный вывод. Операнды выражения должны быть разделены пробелами.
Метасимволы должны быть экранированы. Надо заметить, что 0 возвращается в качестве числа, а не для индикации пустой строки. Строки, содержащие пробелы
или другие специальные символы, должны быть заключены в кавычки. Целые рассматриваются как 32-битные числа.
Ниже приведен список операторов в порядке возрастания приоритета, операции с равным приоритетом заключены в фигурные скобки. Перед символами, которые должны
быть экранированы, стоит \.
<выр> \| <выр>
|
если первое <выр> не пустое и не нулевое, то возвращает его, иначе возвращает второе <выр>
|
<выр> \& <выр>
|
если оба <выр> не пустые и не нулевые, то возвращает первое <выр>, иначе возвращает 0
|
<выр> { =, \>, \>=, \<, \<=, != } <выр>
|
возвращает результат целочисленного сравнения если оба <выр> - целые; иначе возвращает
результат лексического сравнения
|
<выр> { +, - } <выр>
|
сложение и вычитание целочисленных аргументов
|
<выр> { \*, /, % } <выр>
|
умножение, деление и получение остатка от деления целочисленных аргументов
|
<выр> : <выр>
|
оператор сопоставления : сопоставляет первый аргумент со вторым, который должен быть регулярным
выражением. Обычно оператор сравнения возвращает число символов, удовлетворяющих образцу (0 при неудачном сравнении). Однако символы \( и \)
могут применяться для выделения части первого аргумента.
|
Регулярное выражение строится следующим образом:
.
|
- обозначает любой символ
|
*
|
- обозначает предыдущий символ, повторенный несколько раз
|
[]
|
- обозначают любой один из указанных между ними символов; группа символов может обозначаться с помощью
знака "-" (т.е. [0-9] эквивалентно [0123456789]); если после [ стоит ^, то это эквивалентно любому символу, кроме указанных в скобках и
<возврата_каретки>; для указания ] в качестве образца, надо поставить ее сразу за [ (т.е. []...]); . и * внутри квадратных скобок обозначают самих
себя
|
Все остальные символы (и ^, если стоит не в квадратных скобках) обозначают самих себя. Для указания символов ., *,[ и ] надо экранировать их (т.е. писать
\., \*, \[, \]).
Примеры.
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= т.е. добавлением некоторого символа к обеим строкам, что никак не влияет на
результат сравнения, однако позволяет избежать синтаксической ошибки.
5.3. Команда ena
Команда ena позволяет получить части полного имени файла. Первый аргумент - флаг, второй - имя файла. Команда различает следующие флаги:
-n
|
- имя файла без расширения
|
-f
|
- имя файла с расширением
|
-e
|
- расширение
|
-d
|
- имя директории
|
-p
|
- если имя файла начинается с . или .. , то эти символы выделяются из имени
|
Ниже приводится текст программы ena, хранящийся в /util/ena.
# Get part of pathname case $1 in -n ) expr $2 : '.*/\(.*\)[.].*' \| $2 : '\(.*\)[.].*' \| $2 ;; -f ) expr $2 : '.*/\(.*\)' \| $2 ;; -e ) expr $2 : '.*\([.][^./]*\)' \| ' ' ;; -d ) expr $2 : '\(.*\)/.*' \| $2 ;; -p ) expr $2 : '\([.]\)/.*' \| $2 : '\([.][.]\)/.*' \| ' ' ;; * ) echo "error: unknown part of pathname $1" exit 2 ;; esac
|