[ +, - ]
[ *, /, % ]


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

Ниже приведен пример командного файла, содержащего
строки с выражениями:
















- 32 -










# !/bin/csh
# вариант 1
set a = 5
@ a++
echo $a
# результат: 6

# вариант 2
@ a = 7
echo $a
# результат: 7

# вариант 3
set a = 10 b = 15
@ c = ( $a + $b )
echo $c
# результат: 25

# вариант 4
@ c += 5
echo $c
# результат: 30

# вариант 5
@ c = ( $c * 5 )
echo $c
# результат: 150

# вариант 6
@ c *= 5
echo $c
# результат: 750

# вариант 7
@ c *= $c
echo $c
# результат: -27324

# вариант 8
set a = 5 b = 7 c = 9
@ a = ( $a << 2 )
@ b = ( $b >> 2 )
@ c = ( $c + $a + $b )
echo $a $b $c
# результат: 20 1 30

# вариант 9
set a = 5 b = 3
@ c = ( $a | $b )
echo $c
# результат: 7

# вариант 10


- 33 -










set a = 5 b = 3 c = 2
@ d = ( ( $a + $b ) + ( $a + $b + $c ) )
echo $d
# результат: 18

# вариант 11
set a = 5
if( "$a" == "5" ) echo 'Строки идентичны'
if( "$a" != "5" ) echo 'Строки различны '
# результат: Строки идентичны

# вариант 12
date >&gt; file
chmod 755 file
if( -x file ) echo 'Выполняемый'
# результат: Выполняемый

Варианты 1 - 6 самообъяснимы. В варианте 7 получилось отри-
цательное число, так как C-shell оперирует переменными типа
integer (два байта на 16-разрядной ЭВМ).

В выражениях можно использовать операции запроса
свойств файла:

% set c = 0
% @ c = -x a.out + 100
% echo $c
101
% @ c = 100 - -x a.out
% echo $c
99


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

% @ c = 100 - { date }
сре фев 3 14:48:37 МСК 1988
% echo $c
99
% @ c = { date rrrjjj } - 100
Дата: плохой формат
% echo $c
-100


Имеются полезные различия в операциях сравнения строк:







- 34 -










== !=

или

=~ !~

В первом случае в правых частях сравнения не интерпретиру-
ются шаблоны

? . * [...]

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

% set c = "*"
% if( "$c" == "*" ) _____

или

% if( "$c" =~ "*" ) _____

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

1.9. Операторы языка C-shell

Язык C-shell включает следующие операторы: foreach,
switch, while, if_then_else, goto, continue, break, shift,
exit. Операторы можно использовать в интерактивном режиме
работы интерпретатора csh и в командном файле. Принципиаль-
ных различий выполнения операторов в интерактивном режиме и
в командном файле нет. Рассмотрим работу операторов в инте-
рактивном режиме. В процессе ввода оператора интерпретатор
приглашает символом ? продолжать набор, пока не встретит
ключевое слово, означающее конец ввода. Введенный текст
можно рассматривать как временный командный файл, который
интерпретируется и после выполнения уничтожается. Одно из
ключевых слов foreach, switch, while, if_then_else или goto
должно быть первым словом в строке.

Оператор цикла foreach

foreach имя (список слов)
...
end

Переменной имя последовательно присваиваются значения
каждого члена списка слов и выполняется последователь-
ность команд тела цикла foreach. foreach и end должны
находиться в отдельных строках



- 35 -










% foreach i ( a b c d e f g h )
? if( "$i" == "c" ) continue
? glob "$i "
? if( "$i" == "f" ) break
? end
a b d e f %

Переменная цикла i последовательно принимает значения
из списка, объявленного в предложении foreach. Внутри
цикла стоят две проверки. Если значение i равно c, то
перейти к следующему шагу цикла, если значение i равно
f, то прекратить выполнение цикла. В первом случае
оператор continue требует перехода к новой итерации
цикла, во втором - оператор break осуществляет выход за
пределы цикла, и его действие прекращается. Команда
glob работает аналогично команде echo, но после вывода
курсор остается в той же строке, а не в начале следую-
щей.

Оператор выбора switch имеет вид:

switch(входная_строка)
case образец:
...
breaksw
...
default:
...
...
endsw

Образцы вариантов case последовательно сравниваются с
указанной в switch входной строкой (в образцах можно
использовать шаблоны имен файлов *, ? и [...]). Если в
варианте case выявлено совпадение образца и входной
строки, выполняются все строки до ближайшего breaksw,
default или endsw. Если совпадение не обнаружено,
выполнение продолжается после default. Если default
отсутствует, выполнение продолжается после endsw.
Слова case и default должны быть первыми в строке.
Выполнение оператора breaksw приводит к тому, что
управление передается на первую строку после endsw













- 36 -










% set j = 0
% foreach i ( aaa bbb ccc ddd eee )
? @ j++
? switch( $i )
? case "aaa":
? glob "$i "
? breaksw
? case "bbb":
? glob "$i "
? breaksw
? case "ccc":
? glob "$i "
? breaksw
? case "ddd":
? glob "$i "
? breaksw
? default:
? breaksw
?
? endsw
? glob "$j "
?end
aaa 1 bbb 2 ccc 3 ddd 4 5 %

Переменной цикла i присваиваются значения из списка в
предложении foreach. Внутри цикла работает switch.
Если ни одно значение вариантов case не совпадает со
значением переменной i, то выполняется вариант default.
В данном случае это приводит к выходу за пределы перек-
лючателя switch, поэтому выводится порядковый номер
итерации цикла и foreach выполняет следующую итерацию.
В новой итерации цикла снова начинает действовать
switch.

Оператор if

if(выр1) then
...
else if(выр2) then
...
else
...
endif

Если значение выр1 истинно (отлично от нуля), выполня-
ются команды до первого else. Иначе, если значение выр2
истинно, выполняются команды до второго else и т.д.
Возможно любое количество пар else if, endif нужно
только одно. Часть else необязательна. Слова else и
endif должны быть первыми в строках, где они указаны.
Оператор if должен находиться один в строке или после
else



- 37 -










% foreach i ( a b c d e f )
? if( "$i" == "a" ) then
? glob "a "
? else if( "$i" == "b" ) then
? glob "b "
? else if( "$i" == "c" ) then
? glob "c "
? endif
? end
a b c %

На каждой итерации цикла foreach осуществляется про-
верка текущего значения переменной цикла i с символами
'a', 'b' и выполняется, то на экран выводится соот-
ветствующий символ, иначе осуществляется следующая ите-
рация цикла.

Оператор цикла while

while(выражение)
...
end

Цикл выполняется, пока истинно значение выражения. Клю-
чевые слова while и end должны находиться на отдельных
строках. В цикле можно использовать команду break для
выхода из цикла и команду continue для возобновления
следующей итерации цикла без завершения текущей (все
операторы цикла, следующие за командой continue, не
будут выполняться)

% set argv = ( 1 2 3 1 2 3 0 1 )
% while( $#argv > 0 )
? if( "$argv[1]" == "3" ) then
? shift
? continue
? endif
? if( "$argv[1]" == "0" ) then
? break
? endif
? glob " $argv[1]"
? shift
? end
1 2 1 2 %

Здесь выполняется цикл, в котором выводятся значения
argv. Если значение argv[1] есть символ "3", то оно не
выводится и идет переход к следующей итерации цикла,
если символ "0", то действие цикла прекращается. Опера-
тор shift освобождает (выталкивает) вершину стека для
следующего элемента. В данном случае под стеком понима-
ется список слов массива argv. После каждого сдвига
argv[1] приобретает значение следующего слова. Цикл


- 38 -










while прекращает работу, когда список слов массива argv
станет пустым, т.е. $#argv станет равным нулю.

1.10. Командные файлы

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

Каждый командный файл на языке C-shell должен начи-
наться символом # в первой позиции первой строки, далее ука-
зывается системное имя интерпретатора. Допускаются пустые
строки. Строка, начинающаяся #, является строкой коммента-
риев. При создании командных файлов, используя переменную
argv, можно организовать ввод и обработку аргументов команд-
ной строки, которые могут быть как именами файлов, так и
любыми последовательностями символов. В качестве примера
рассмотрим программу диалогового ввода содержания документа.
Комментарии в программе достаточно полно раскрывают алгоритм
работы






























- 39 -










#!/bin/csh
# Программа в режиме меню запрашивает
# сведения о загрузке ЭВМ. Результат
# ввода дописывается в файл Result.
# Исправление ошибок ввода выполняется
# повторным вводом. Запись в файл
# происходит по команде Запомнить.
# Переменная out используется для
# указания направления вывода. Когда
# out = /dev/tty вывод дописывается на
# экран дисплея, когда out = Result
# вывод дописывается в файл ./Result.

set ЭВМ НОМ ОРГ ПОД
set out = /dev/tty
set мес = ( 0 0 0 0 0 0 0 0 0 0 0 0 )
set сум = ( 0 0 0 0 0 )

# Имена месяцев для подтверждения
# режима ввода

set имя = ( Январь Февраль Март \
Апрель Май Июнь \
Июль Август Сентябрь \
Октябрь Ноябрь Декабрь )

# Работа программы выполняется в
# бесконечном цикле while(1)

while ( 1 )
glob ' Укажите режим работы > '
set ответ = $<&lt;
switch( "$ответ" )

case '[КкKk]':
exit( 0 )

case '[ЗзZz]':
set out = Result

case '[ДдDd]':

# Вычисление показателей по кварталам
# и за год

@ сум[1] = $мес[1] + $мес[2] + $мес[3]
@ сум[2] = $мес[4] + $мес[5] + $мес[6]
@ сум[3] = $мес[7] + $мес[8] + $мес[9]
@ сум[4] = $мес[10] + $мес[11] + $мес[12]
@ сум[5] = $сум[1] + $сум[2] + $сум[3] + $сум[4]

# Очищать экран, если вывод не в файл



- 40 -










if( "$out" != "Result" ) clear

# Команда echo выводит в файл out
# значения переменных

echo " \
Отчет о загрузке ЭВМ.\
ЭВМ $ЭВМ \
Заводской номер $НОМ \
Организация $ОРГ \
Подразделение $ПОД \
Январь $мес[1] \
Февраль $мес[2] \
Март $мес[3] \
Первый квартал $сум[1] \
Апрель $мес[4] \
Май $мес[5] \
Июнь $мес[6] \
Второй квартал $сум[2] \
Июль $мес[7] \
Август $мес[8] \
Сентябрь $мес[9] \
Третий квартал $сум[3] \
Октябрь $мес[10] \
Ноябрь $мес[11] \
Декабрь $мес[12] \
Четвертый квартал $сум[4] \
Итого $сум[5] " >> $out
continue

case '[АаAa]':
glob 'Тип ЭВМ: '
set ЭВМ = $<&lt;
continue

case '[БбBb]':
glob 'Заводской номер ЭВМ: '
set НОМ = $<&lt;
continue

case '[ВвWw]':
glob 'Организация: '
set ОРГ = $<&lt;
continue

case '[ГгGg]':
glob 'Подразделение: '
set ПОД = $<&lt;
continue

case '[1-9]':
case "1[012]":
glob $имя[$ответ]': '


- 41 -










set мес[$ответ] = $<&lt;
continue

default:
# Вывод меню, если режим указан неправильно.
echo 'Такого режима нет.'
clear
echo ' \
\
\
\
\
\
Режимы работы: \
\
а Ввод наименования ЭВМ. \
б Ввод заводского номера ЭВМ. \
в Ввод наименования организации. \
г Ввод наименования подразделения. \
д Вывод данных на экран. \
з Запомнить. \
к Конец работы. \
Вывод загрузки в часах по месяцам: \
1 Январь 2 Февраль 3 Март \
4 Апрель 5 Май 6 Июнь \
7 Июль 8 Август 9 Сентябрь \
10 Октябрь 11 Ноябрь 12 Декабрь \
\
'
endsw
end

Ниже показано содержимое файла Result, который формирует
программа. Эта же информация выводится на экран, если указан
режим Вывод данных




















- 42 -










Отчет о загрузке ЭВМ.
ЭВМ СМ 1420
Заводской номер 1673
Организация Поликлиника 124
Подразделение ИВЦ
Январь 300
Февраль 350
Март 350
Первый квартал 1000
Апрель 520
Май 330
Июнь 700
Второй квартал 1550
Июль 200
Август 150
Сентябрь 250
Третий квартал 600
Октябрь 300
Ноябрь 310
Декабрь 280
Четвертый квартал 890
Итого 4040


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
























- 43 -










# !/bin/csh
# программа демонстрирует способ чтения
# со стандартного ввода символов ? и *,
# которые обычно рассматриваются как
# шаблоны имен файлов и интерпретируются
#
while( 1 )
glob '=> '
set ответ = "$<&lt;"

switch( "$ответ" )

case [?] :
echo 'Вопросительный знак'
breaksw

case [*] :
echo 'Звездочка'
breaksw

case '{' :
case '}' :
echo 'Фигурная скобка'
breaksw

default :
echo 'Другой символ'

endsw
end


1.11. Протоколирование, средства работы с протоколом

Интерпретатор записывает во временный файл протокол
работы пользователя в виде списка выполненных командных
строк. Количество запоминаемых командных строк определяется
переменной history, которая обычно определяется в файле
~/.cshrc (о нем будет сказано ниже). Если установлена пре-
допределенная переменная savehist, то по завершению сеанса
работы пользователя указанное количество строк history будет
сохранено в файле ~/.history. При следующем входе в систему
содержимое этого файла используется для занесения в прото-
кол. Например, если выполнена команда

set savehist = 22

то последние 22 строки протокола будут сохранены в файле
~/.history и восстановлены в начале следующего сеанса
работы. Чтобы напечатать протокол, необходимо выполнить
команду history. Каждая строка протокола имеет номер, что
позволяет запустить ее на выполнение, указывая, например,
соответствующий номер. Восклицательный знак в командной


- 44 -










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

1 cat file1
2 pr -w39 -l24 -2 file1
3 cc program.c >&gt;& errors &
4 cat errors
5 ed program.c
6 history

тогда, используя восклицательный знак, можно выполнить ряд
действий:

!2
выполнится вторая строка протокола;

!!
выполнится последняя строка протокола:

!-2
выполнится четвертая строка (вторая от последней);

!cat или !c
выполнится четвертая строка. Интерпретатор просматри-
вает строки протокола снизу и выполняет первую, в кото-
рой найдена последовательность символов (cat или c),
стоящая в начале строки;

!{cat}.a1
выполнится команда cat errors.a1 - к найденной строке
дописывается .a1;

!?gram?
выполнится пятая строка протокола. Интерпретатор выбе-
рет для выполнения эту строку, так как в ней будет най-
ден шаблон gram. Здесь символы ? выделяют шаблон, по
которому осуществляется поиск;

cat !5* !1*
выполнится команда cat program.c file1 - будут подстав-
лены слова пятой и первой строк протокола, исключая
первые слова этих строк.


Можно выбирать отдельные слова в строках протокола для
включения их в командную строку. Слова командной строки
нумеруются, начиная с 0. Слово с номером 0 - обычно имя
команды. Слово можно выделить с помощью определителя, перед
которым необходимо указать символ двоеточие, например



- 45 -










cat !3:1

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

cat program.c

Рассмотрим подробнее определители слов в командных строках
протокола:

* или n* или n-m
выбрать все слова, начиная со слова с номером 1, или
выбрать все слова, начиная со слова с номером n, или
выбрать все слова, начиная со слова с номером n и кон-
чая словом с номером m;

n или n-, или -n
выбрать слово с номером n, или выбрать все слова, начи-
ная со слова с номером n, не включая последнее, или
выбрать все слова, начиная со слова с номером 0 до
слова с номером n;

?шаблон?:%
выбрать слово, соответствующее шаблону;

^ или $
слово с номером 1 или последнее слово командной строки.


Разрешается не указывать двоеточие перед следующими
определителями:

^ $ * - %

Рассмотрим пример. Пусть после выполнения команды history
на экран дисплея выведен протокол:

1 cat file1 file2 file3
2 pr -w39 -l24 -2 file1 file5
3 cc -o program1.c program2.c >&gt;& errors &
4 cat errors
5 ed program2.c
6 history

тогда интерпретатор csh выполнит команды, осуществляя подс-
тановки следующим образом:

!5:0 !1:3
из пятой строки выбирается слово с номером 0 ( имя
команды ), из первой строки выбирается слово с номером
3. Выполнится команда ed file3;




- 46 -










!5:0 !1$
из пятой строки выбирается слово с номером 0, из первой
строки - последнее слово. Выполнится команда ed file3;

!2:-3 !3:2-3
из строки 2 выбираются слова с номерами от 0 до 3 вклю-
чительно, из строки 3 выбираются слова с номерами 2 и
3. Выполнится команда:

pr -w39 -l24 -2 program1.c program2.c


!2-3 !?prog?%
выполнится команда:

pr -w39 -l24 -2 program2.c



После необязательного определителя могут указываться
модификаторы слов, которые позволяют выполнить ряд преобра-
зований над словом, и оно подставляется в командную строку
модифицированным. Модификаторы переменных были рассмотрены
выше. В действиях со строками протокола можно использовать
и другие модификаторы:

p
распечатать новую команду, но не выполнять ее;

&
повторить предыдущюю подстановку;

s/образец_1/образец_2/
заменить образец_1 на образец_2. Символ / можно заме-
нить на любой, отсутствующий в образцах. Если обра-
зец_2 пустая строка, то образец_1 удаляется.


Перед каждым модификатором необходимо ставить двоето-
чие. Если имеется определитель слова, то модификатор должен
следовать за ним. Пусть после выполнения команды history на
экран дисплея выведено:

1 cat /usarc/gruppa/ivanov/file1.c
2 pr /usarc/gruppa/ivanov/file1.c
3 cc pa1.c pa2.c pa3.c pa4.c >&gt;& errors &
4 cat errors
5 ed program.c
6 history

тогда интерпретатор выполнит команды, осуществляя подста-
новки и модификации, следующим образом:



- 47 -










!1:0 !1^:t:r
выбирает из строки с номером 1 слово с номером 0, т.е.
имя команды, в данном случае cat. Далее выбирает из
первой строки слово с номером 1, в данном случае это
/usarc/gruppa/ivanov/file1.c. Модификатор t удалит из
этого слова имена каталогов, в данном случае удаляется
/usarc/gruppa/ivanov, и слово теперь будет именем файла
file1.c. Модификатор r удалит расширение имени файла.
Таким образом, выполнится команда cat file1.

!1:0 !1^:h/document
по определителю ^ будет выбрано первое слово первой
строки, модификатор h удалит из него имя файла, оставив
имена каталогов, ведущих к нему, и выполнится команда

cat /usarc/gruppa/ivanov/document


!1:0 !1^:h:s?ivanov?sidorov?/document
из первого слова первой строки выбираются имена катало-
гов, ведущих к файлу, затем модификатор s заменит
ivanov на sidorov и выполнится команда

cat /usarc/gruppa/sidorov/document


!1:0 !1^:h:s?ivanov?sidorov?/doc !1^:&:p
первые два слова командной строки действуют аналогично
предыдущему примеру. Третье слово выбирает из 1 строки
протокола слово с номером 1, в нем осуществляется
замена ( модификатор & ), аналогичная предыдущей, т.е.
выполняется замена ?ivanov?sidorov?, сохранив все
остальное в этом слове. Строка не выполняется, а только
выводится на экран (модификатор p):

cat /usarc/gruppa/sidorov/doc \
/usarc/gruppa/sidorov/file1.c


!1:0 !3:1-4:gs?pa?ff?:p
имя команды выбирается из первой строки протокола, из 3
строки выбираются все слова с номерами от 1 до 4 вклю-
чительно и в них глобально (модификатор g) делается
замена ?pa?ff? . Команда будет напечатана, но выпол-
няться не будет (модификатор p):

cat ff1.c ff2.c ff3.c ff4.c


Существует также удобное средство редактирования пос-
ледней строки протокола. Для этих целей используется конст-
рукция ^шаблон^замена^. Допустим, последняя строка имеет
вид cat aaa bbb ccc ddd, тогда после команды ^ccc^file.c^


- 48 -










будет выполнена замена: cat aaa file.c ccc ddd.

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

alias sp "sort \!* | print"

тогда командные строки

sort file1 file2 | print

и

sp file1 file2

тождественны. Вместо !* в командную строку будут подстав-
лены имена файлов или ключи команды sort, указанные за псев-
донимом sp.