Интерпретатор командного языка shell
Shell - командный язык, могущий выполнять как команды,
введенные с терминала, так и команды, хранящиеся в файле.
Этот текст подготовлен НПО "КЛОТО"
Оглавление
1. Основные понятия языка shell . . . . . . . . . . . . . .
1_1. Ввод-вывод . . . . . . . . . . . . . . . . . . . . . .
1_2. Синхронное и асинхронное выполнение команд . . . . . .
1_3. Конвейер . . . . . . . . . . . . . . . . . . . . . . .
1_4. Метасимволы, генерация имен файлов . . . . . . . . . .
2_ Синтаксис языка shell . . . . . . . . . . . . . . . . .
2_1. Комментарии . . . . . . . . . . . . . . . . . . . . .
2_2. Подстановка результатов выполнения команд . . . . . .
2_3. Переменные и подстановка их значений . . . . . . . . .
2_4. Специальные переменные . . . . . . . . . . . . . . . .
3_ Управляющие конструкции . . . . . . . . . . . . . . . .
3_1. Цикл ДЛЯ . . . . . . . . . . . . . . . . . . . . . . .
3_2. Оператор выбора . . . . . . . . . . . . . . . . . . .
3_3. Условный оператор . . . . . . . . . . . . . . . . . .
3_4. Цикл ПОКА . . . . . . . . . . . . . . . . . . . . . .
3_5. Функции . . . . . . . . . . . . . . . . . . . . . . .
3_6. Зарезервированные слова . . . . . . . . . . . . . . .
3_7. Специальные команды . . . . . . . . . . . . . . . . .
4_ Выполнение shell-программ . . . . . . . . . . . . . . .
4_1. Запуск shellа . . . . . . . . . . . . . . . . . . . .
4_2. Выполнение . . . . . . . . . . . . . . . . . . . . . .
4_3. Окружение . . . . . . . . . . . . . . . . . . . . . .
4_4. Сигналы . . . . . . . . . . . . . . . . . . . . . . .
4_5. Замечания . . . . . . . . . . . . . . . . . . . . . .
5_ Дополнительные сведения . . . . . . . . . . . . . . . .
5_1. Команда test . . . . . . . . . . . . . . . . . . . . .
5_2. Команда expr . . . . . . . . . . . . . . . . . . . . .
5_3. Команда ena . . . . . . . . . . . . . . . . . . . . .
* 1. Основные понятия языка shell *
Три направления ввода-вывода являются выделенными - стан-
дартный ввод, стандартный вывод и стандартный протокол. Как
правило, команды берут исходные данные из стандартного ввода и
помещают результаты в стандартный вывод.
Стандартные ввод, вывод и протокол можно переназначить.
Обозначение
< <имя файла>
служит для переназначения стандартного ввода (дескриптор файла
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 - - <1_2. Синхронное и асинхронное выполнение команд
Обычно shell ждет завершения выполнения команды. Однако
имеется возможность запустить задачу в асинхронном режиме, т.е.
без ожидания ее завершения. Для этого после команды (после всех
ее аргументов и указаний о переназначении ввода-вывода) надо
поставить знак &. При этом по умолчанию стандартный ввод коман-
ды назначается на пустой файл /dev/null.
Пример: создать файл primer можно по команде
echo > primer
Еще пример: запустить программу prog в асинхронном режиме, что-
бы не надо было дожидаться его завершения, засечь время выпол-
нения, результаты программы направить в файл prog.res, данные о
времени выполнения - в файл prog.tim.
time prog > prog.res 2> prog.tim &
Конвейер - последовательность команд, разделенных знаком |.
Если после конвейера стоит ; shell ждет его завершения. Если &
- то не ждет. Роль ; может играть конец строки. Смысл конвейера
в том, что стандартный вывод одной команды замыкается на стан-
дартный ввод другой. Пример конвейера - подсчитать число объ-
ектных файлов в текущем каталоге.
ls *.o | wc -l
1_4. Метасимволы, генерация имен файлов
Метасимволы - символы, имеющие специальное значение для
интерпретатора :
? * ; & ( ) | ^ < > <пробел> <табуляция> <возврат_каретки>
Однако каждый из этих символов может представлять самого себя,
если перед ним стоит \. Все символы, заключенные между кавычка-
ми ' и ', представляют самих себя. Между двойными кавычками (")
выполняются подстановки команд (см п. 2.2) и параметров (см. п.
2.3), а символы \, `," и $ могут экранироваться предшествующим
символом \.
После всех подстановок в каждом слове команды ищутся сим-
волы *,?, и [. Если находится хотя бы один из них, то это слово
рассматривается как шаблон имен файлов и заменяется именами
файлов, удовлетворяющих данному шаблону (в алфавитном порядке).
Если ни одно имя файла не удовлетворяет шаблону, то он остается
неизменным. Значения указанных символов:
* любая строка, включая и пустую
? один любой символ
[...] любой из указанных между ними символов. Пара
символов, разделенных знаком -, означает любой
символ, который находится между ними, включая и
их самих. Если первым символом после "[" идет
"!", то указанные символы не должны входить в
имя файла
* 2_ Синтаксис языка shell *
Строки, начинающиеся с #, трактуются как комментарии.
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+статус, если она завершилась аварийно.
Список - это последовательность одного или нескольких кон-
вейеров, разделенных символами ;, &, && или || и быть может за-
канчивающаяся символом ; или &. Из четырех указанных операций ;
и & имеют равные приоритеты, меньшие, чем у && и ||. Приоритеты
последних также равны между собой. Символ ; означает, что кон-
вейеры будут выполняться последовательно, а & - параллельно.
Операция && (||) означает, что список, следующий за ней будет
выполняться лишь в том случае, если код завершения предыдущего
конвейера нулевой (ненулевой).
Команда - это либо простая команда, либо одна из управляю-
щих конструкций. Кодом завершения команды является код заверше-
ния ее последней простой команды.
for <переменная> [ in <набор> ]
do
<список>
done
Если часть in <набор> опущена, то это означает in "$@" ( то
есть in $1 $2 ... $n). Пример. Вывести на экран все фортранные
файлы текущей библиотеки:
for f in *.for
do
cat $f
done
case $<переменная> in
<шаблон> | <шаблон>... ) <список> ;;
. . .
esac
Оператор выбора выполняет <список>, соответствующий первому
<шаблону>, которому удовлетворяет <переменная>. Форма шаблона
та же, что и используемая для генерации имен файлов. Часть
| шаблон... может отсутствовать.
Пример. Определить флаги и откомпилировать все указанные файлы.
# инициализировать флаг
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
if <список1>
then
<список2>
[ elif <список3>
then
<список4> ]
. . .
[ else
<список5> ]
fi
Выполняется <список1> и, если код его завершения 0, то выполня-
ется <список2>, иначе - <список3> и, если и его код завершения
0, то выполняется <список4>. Если же это не так, то выполняется
<список5>. Части elif и else могут отсутствовать.
while <список1>
do
<список2>
done
До тех пор, пока код завершения последней команды <списка1>
есть 0, выполняются команды <списка2>.
При замене служебного слова while на until условие выхода
из цикла меняется на противоположное.
В качестве одной из команд <списка1> может быть команда
true (false). По этой команде не выполняется никаких действий,
а код завершения устанавливается 0 (-1). Эти команды применяют-
ся для организации бесконечных циклов. Выход из такого цикла
можно осуществить лишь по команде break (см. Специальные коман-
ды).
<имя> () {
<список>;
}
Определяется функция с именем <имя>. Тело функции - <список>,
заключенный между { и }.
3_6. Зарезервированные слова
Следующие слова являются зарезервированными:
if then else elif fi
case in esac
for while until do done
{ }
Как правило, для выполнения каждой команды 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-программ *
Программа, интерпретирующая shell-программы, находится в
файле /bin/sh. При запуске ее первый аргумент является именем
shell-программы, остальные передаются как позициональные пара-
метры. Если файл, содержащий shell-программу, имеет право вы-
полнения (x), то достаточно указания лишь его имени. Например,
следующие две команды операционной системы эквивалентны (если
файл ficofl обладает указанным правом и на самом деле содержит
shell-программу):
sh ficofl -d . g\*
и
ficofl -d . g\*
При выполнении shell-программ выполняются все подстановки.
Если имя команды совпадает с именем специальной команды, то она
выполнается в рамках текущего процесса. Так же выполняются и
определенные пользователем функции. Если имя команды не совпа-
дает ни с именем специальной команды, ни с именем функции, то
порождается новый процесс и осуществляется попытка выполнить
указанную команду.
Переменная PATH определяет путь поиска директории, содер-
жащей данную команду. По умолчанию это
::/bin:/usr/ bin:/util:/dss/rk
Директории поиска разделяются двоеточиями; :: означает текущую
директорию. Если имя команды содержит символ /, значение $PATH
не используется: имена, начинающиеся с / ищутся от корня, ос-
тальные - от текущей директории. Положение найденной команды
запоминается shellом и может быть опрошено командой hash.
Окружение - это набор пар имя-значение, которые передаются
выполняемой программе. Shell взаимодействует с окружением нес-
колькими способами. При запуске shell создает переменную для
каждой указанной пары, придавая ей соответствующее значение.
Если вы измените значание какой-либо из этих переменных или
создадите новую переменную, то это не окажет никакого влияния
на окружение, если не будет использована команда export для
связи переменной shellа с окружением (см. также set -a). Пере-
менная может быть удалена из окружения командой unset (см.).
Таким образом, окружение каждой из выполняемых shellом команд
формируется из всех неизмененных пар имя-значение, первоначаль-
но полученных shellом, минус пары, удаленные командой unset,
плюс все модифицированные и измененные пары, которые для этого
должны быть указаны в команде export.
Окружение простых команд может быть сформировано указанием
перед ней одного или нескольких присваиваний переменным. Так,
TERM=d460 <команда>
и
(export TERM; TERM=d460; <команда>)
эквивалентны. Переменные, участвующие в таких присваиваниях,
назовем ключевыми параметрами.
Если установлен флаг -k (см. set), то все ключевые пара-
метры помещаются в окружение команды, даже если они записаны
после команды.
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 sys-
tem call)
SIGPIPE - 13 - запись в канал без чтения из него (write on a
pipe with no one to read it)
SIGALRM - 14 - будильник (alarm clock)
SIGTERM - 15 - программное завершение процесса (software ter-
mination signal)
Сигналы SIGINT и SIGQUIT игнорируются, если команда была
запущена асинхронно. Иначе сигналы обрабатываются так же, как в
процессе-предке, за исключением сигнала SIGSEGV (см. также Спе-
циальные команды. Trap).
При выполненнии команд запоминается их местонахождение.
Поэтому при создании команды с тем же именем, но находящейся в
другой директории, все равно будет выполняться старая команда
(если вызов происходит по короткому имени). Для исправления си-
туации воспользуйтесь командой hash с ключом -r (см. Специаль-
ные команды).
Если вы переименовали текущую или вышележащую директорию,
то команда pwd может давать неверную информацию. Для исправле-
ния ситуации воспользуйтесь командой cd с полным именем дирек-
тории.
* 5_ Дополнительные сведения *
Команда test применяется для проверки условия. Формат вы-
зова:
test <выражение>
или
[ <выражение> ]
Команда test вычисляет <выражение> и, если его значение - исти-
на, возвращает код завершения 0 (true); иначе - ненулевое зна-
чение (false). Ненулевой код завершения возвращается и если
опущены аргументы. <Выражение> может состоять из следующих при-
митивов:
-r файл - истина, если файл существует и доступен для
чтения
-w файл - истина, если файл существует и доступен для
записи
-x файл - истина, если файл существует и является вы-
полняемым
-f файл - истина, если файл существует и является обыч-
ным файлом
-d файл - истина, если файл существует и является ди-
ректорией
-c файл - истина, если файл существует и является спе-
циальным символьно-ориентированным файлом
-b файл - истина, если файл существует и является спе-
циальным блок-ориентированным файлом
-p файл - истина, если файл существует и является име-
нованным каналом (pipe)
-s файл - истина, если файл существует и имеет ненуле-
вую длину
-t [ дескриптор файла ]
- истина, если открытый файл с указанным деск-
риптором (по умолчанию 1) существует и ассоции-
рован с терминалом
-zho 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
Команда 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 на самом деле является знаком ра-
венства. Так как аргументы предварительно обрабатываются shel-
lом, то команда
expr $a = '='
будет воспринята как
expr = = =
что синтаксически некорректно. В подобных случаях надо пользо-
ваться таким приемом:
expr X$a = X=
т.е. добавлением некоторого символа к обеим строкам, что никак
не влияет на результат сравнения, однако позволяет избежать
синтаксической ошибки.
Команда 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
Last-modified: Sun, 07 Jul 2002 09:31:58 GMT