Введение в UNIX
Дегтярев Е.К.
Оглавление
8. C-SHELL
Язык и интерпретатор языка C-Shell появился в версии сис-
темы UNIX Калифорнийского университета в Беркли UNIX BSD4.2
для VAX-11. Основные достоинства этой версии заключаются в
добавлении в UNIX редакторов ex и vi, интерпретатора
C-Shell, реализации языков ПАСКАЛЬ и ЛИСП, базы данных
INGRES и других возможностей.
В начало страницы
Стандартным знаком подсказки является процент (%). При
желании его можно заменить.
Восклицательный знак ( ! ) выполняет многие специальные
функции, в частности ( !! ) означает вызов предыдущей коман-
ды.
Знак крышка ( ^ ) используется для разделения строк при
коррекции части текста предыдущей команды.
Знак тильда ( ~ ) в качестве префикса имени пользователя
расширяет его до полного имени его рабочего каталога.
Фигурные скобки ({ }) группируют список имен файлов в
группу имен файлов.
Когда вы входите в C-Shell, он ищет в вашем рабочем ката-
логе файлы .login и .cshrc. Если такие файлы у вас есть, он
выполняет все команды, расположенные в них. Файл .login ис-
пользуется только при входе в C-Shell с терминала;
.cshrc - при любом входе.
В начало страницы
Встроенный механизм истории интерпретатора C-Shell хранит
заданное число последних введенных вами команд. Число храни-
мых команд равно значению предопределенной переменной
history, которую вы можете установить в файле .cshrc коман-
дой set:
% set history = 15
(в отличие от Shell при установке переменной требуется слово
set).
Чтобы посмотреть хранимые команды, надо распечатать на
экране буфер механизма истории командой history, например:
% history
1 ls -l
2 mail
3 history
%
Механизм истории обеспечивает возможность вызвать любую
из хранимых команд, печатая восклицательный знак и номер ко-
манды, например:
% ! 1
ls -l
. . . .
%
В начало страницы
Имеются различные средства для повторного исполнения пре-
дыдущих команд, возможно, с изменением части повторяемой ко-
манды.
Для коррекции непосредственно предыдущей команды есть
следующие средства редактирования.
Пример:
% cd /users/peter/shels
/users/peter/shels: No such file or directory.
Допущена ошибка: shels вместо shells. Она исправляется
следующим образом:
%^shels^shells^
cd/users/peter/shells
%
Исправленная команда заносится в буфер истории:
% history
1 ls -l
2 mail
3 history
4 cd /users/peter/shels
5 cd /users/peter/shells
6 history
Чтобы редактировать произвольную предыдущую команду, мож-
но воспользоваться командой s (substitution) подстановки
(см. раздел 8.6).
В начало страницы
Исполнение предыдущих команд, сохраненных в буфере исто-
рии, без повторного их набора можно осуществить различными
способами.
Первый способ: напечатать восклицательный знак и имя ко-
манды. Исполняется самая последняя команда из буфера истории
с этим именем.
Например:
% !cd
cd /users/peter/shells.
Необязательно печатать полное имя. Достаточно минимально-
го количества символов начала имени, необходимого для одноз-
начного его опознания в буфере истории,
например:
% !c
cd /users/peter/shells.
Второй способ: напечатать и номер команды в буфере исто-
рии без пробела между ними.
Например:
% !1
ls -l
<вывод команды ls -l>
%
Наконец, имеется возможность использования последнего
слова непосредственно предыдущей команды вводом двух зна-
ков !$,
например:
% mv /users/wowa/spasewar.c space.c
% pr !$ | lpr
pr space.c | lpr
%
В начало страницы
Для исполнения частично измененных предыдущих команд ис-
пользуется средство подстановки :s (substitution) части
текста (похожее на аналогичное средство в редакторе ex).
Пусть имеется следующий буфер истории:
% history
1 ls -l
2 mail
3 cd /users/peter/shels
4 cd /users/peter/shells
5 history
6 cd /users/peter/shells
7 ls -l
8 mv /users/wowa/spacewar.c space.c
9 pr space.c | lpr
10 history
Используем средство подстановки для изменения и испол-
нения команды mv:
% !8 : s /spacewar/empire/
mv /users/wowa/empire.c space.c.
В начало страницы
Знак тильда (~) используется в C-Shell для ссылки на
собственный рабочий каталог или рабочий каталог другого
пользователя, указанного именем пользователя.
Примеры:
% cd progs
% mv ~/test.c
Последняя точка означает текущий каталог progs. Чтобы уз-
нать, что же в действительности выполнено, посмотрим буфер
истории:
% !h
. . . . . . .
. . . . . . .
11 mv /users/wowa/empire.c space.c
12 cd progs
12 mv /users/peter/test.c .
Пусть имеется пользователь с именем nick. Чтобы узнать
его рабочий каталог, можно использовать команду echo и
средство знака тильда:
% echo ~nick
/users/nick
%
В начало страницы
Кроме средств метасимволов для ссылки на множество файлов
в C-Shell применяется средство группирования имен файлов для
явного указания множества файлов в виде спискф имен файлов,
заключенного в фигурные скобки.
Пример:
% cp /users/peter/animals/{cats, dogs, birds}
Или: % cp ~mary/animals/{cats, dogs, birds}.
Эта команда копирует множество из трех файлов с именами:
/users/peter/animals/cats
/users/peter/animals/dogs
/users/peter/animals/birds
В одной команде можно использовать более одной группы
файлов, например:
% echo ls{/bin, /usr/ucb}{pi, is}
ls /bin/pi /bin/is /usr/ucb/pi /usr/ucb/is
В начало страницы
Этот механизм, называемый alias, позволяет дать дополни-
тельные (обычно короткие) имена часто используемым (обычно
длинным) командам.
Пример:
% alias cdm1 cd /users/sys/doce/mans/man/man1
% alias cdm2 cd /users/sys/doce/mans/man/man2
% alias cdm3 cd /users/sys/doce/mans/man/man3
Чтобы изменить текущий каталог, например, на ...man 2,
достаточно ввести соответствующую команду по ее дополнитель-
ному имени:
% cdm2
% pwd
/users/sys/doce/mans/man/man2.
Те же переименования можно выполнить короче с использова-
нием ссылки !$ на последнее слово команды:
% alias cdm cd /users/sys/docs/mans/man/man \!$
% cdm 3
% pwd
/ users/sys/docs/mans/man3.
Обратный слэш перед восклицательным знаком исключает
действие восклицательного знака как специального символа.
Отмена переименования производится командой unalias, нап-
ример:
% unalias cdm.
В начало страницы
Подобно языку Shell, C-Shell имеет встроенные переменные,
установка которых может влиять на поведение интерпретатора.
Установка значения переменной производится командой set,
имеющей следующий синтаксис:
set <переменная> = <значение>
Рассмотрим наиболее употребительные встроенные перемен-
ные.
Переменная history задает количество предыдущих команд,
сохраняемых в буфере истории, например: set history = 30.
Переменная path устанавливает каталоги для поиска команд.
Список каталогов, разделенных пробелами, заключается в скоб-
ки:
set path = (/bin /usr/ucb $Home/bin .)
Переменная prompt задает строку подсказки перед выполне-
нием очередной команды. При этом символы \ ! (обратный слэш
и восклицательный знак) в строке подсказки задают текущий
номер команды, используемый в механизме истории.
Пример:
% set prompt = "ed \ ! >"
ed5> history
. . . . . . . .
5 history
Переменная Shell указывает, какой интерпретатор вы хотите
в качестве начального. Возможные значения: /bin/csh или
/bin/sh.
Булевская переменная noclobber используется для защиты
уже существующего файла от случайной потери путем перезаписи
в него при перенаправлении стандартного вывода. Для этого ее
надо установить в значение "истина":
% set noclobber
% fgrep ounds /usr/dict/words > shells
Shells: File exists -
(файл с именем shells уже существует и его текущая версия
была бы потеряна). Если вы тем не менее хотите перезаписать
этот файл, используйте перенаправление с восклицательным
знаком (>!):
% fgrep ounds /usr/dict/words >! shells
В этом случае перезапись состоится. Установка булевской
переменной в противоположное значение "ложь" выполняется ко-
мандой:
unset noclobber.
Переменные home и cwd, устанавливаемые автоматически,
равны полным именам собственного и текущего каталогов соот-
ветственно.
Переменная status автоматически возвращает нулевое значе-
ние, если текущая команда завершена без ошибок. Ненулевое
значение указывает ошибочное завершение.
Переменная argv содержит аргументы командной строки с ну-
мерацией аргументов следующим образом: argv [0] - команда,
argv [1] - первый аргумент и так далее (как в языке C).
Доступ к переменным обеспечивается ссылкой на имена с
предшествующим знаком $, например, $cwd, $argv [0] и т.д.
Посмотреть текущие значения встроенных переменных можно
командой set без параметров:
% set
Пользователь может определить свои переменные типа строка
знаков.
Например:
% set wd = `pwd`
% echo $wd
/users/sys/docs.
Здесь результат выполнения команды pwd (строка полного
имени рабочего каталога пользователя) присвоен переменной
wd, значение которой проверено командой echo.
Кроме строковых переменных можно определить числовые пе-
ременные, принимающие значения типа целое, вещественное или
булевское. Целое и вещественное значение начинающееся с ну-
ля, считается восьмеричным, иначе - десятичным. Установка
значения числовой переменной выполняется командой @ (аналог
set для строковых переменных).
Пример:
% @ sum = (1 + 4)
% echo $sum
5
В общем случае синтаксис команды @ такой:
@ <переменная> ,
где C-операция - один из операторов присваивания, приня-
тых в языке C (=, +=, -=, *=, /=, %=), а C-выражение - выра-
жение в синтаксисе языка C.
В начало страницы
Метасимволами называются символы, имеющие специальное
значение для интерпретатора.
В C-Shell имеются следующие метасимволы:
- синтаксические;
- именования файлов;
- кавычки;
- ввода - вывода;
- подстановки;
- прочие.
Многие из них сходны по функциям с аналогичными функциями
метасимволов обычного Shell.
Синтаксические метасимволы:
; - разделяет команды, которые будут выполнены последова-
тельно;
| - разделяет команды, соединенные каналом, так что стан-
дартный вывод левой является стандартным вводом правой;
|& - аналогично |, однако диагностический вывод тоже нап-
равляется на ввод следующей команды;
( ) - объединяют команды, разделенные предыдущими знака-
ми, в единое целое для использования в последовательности
или с каналом;
& - предписывает выполнение команды на заднем плане па-
раллельно со следующей командой, например:
cat letter>/dev/lp &
|| - аналогичен знаку |, однако правая команда выполняет-
ся, только если левая завершилась аварийно;
&& - аналогичен знаку |, однако правая выполняется, толь-
ко если левая завершилась нормально.
Метасимволы именования файлов:
? - любой символ в имени файла. Например, файлы fa.o,
fb.o, fc.o могут быть напечатаны одной командой:
$ cat f?.o > total.o
* - любая строка в имени файла. Например, удаление всех
файлов, имена которых начинаются с old:
% rm old*
[] - любая одна буква из указанного в квадратных скобках
диапазона. Например:
% ls f.[a - z] - печать всех файлов типа f.x, где x -
буква из диапазона a - z;
{} - аналогичны квадратным скобкам [], однако вместо диа-
пазона указано множество букв. Например, печать файлов list,
last, lost:
% ls l{iao}st;
~ - полное имя рабочего каталога пользователя (см.выше);
/ - разделяет имена каталогов и файла в полном имени
файла или каталога.
Метасимволы - кавычки:
\ - отменяет мета-значение следующего за ним одного мета-
символа. Например:
% ls \*
* not found
(в то время как % ls * - печать всех файлов текущего ка-
талога)
' ' - отменяет мета-значения группы символов. Пример:
% set string = 'ws - l $dir / $file'
" " - аналогичны одиночным кавычкам, однако подстановка
значений переменных и команд выполняется. Пример:
% echo "$dir is not a directory."
Метасимволы ввода - вывода:
< - перенаправление ввода;
> - перенаправление вывода (если переменная noclobber ус-
тановлена, перезапись существующего файла вывода не происхо-
дит);
>& - перенаправление диагностического вывода;
>! - перенаправление вывода (с обязательной перезаписью
существующего файла вывода);
>&! - аналогично >! для диагностического вывода;
>> - аналогично >, однако вывод добавляется в конец су-
ществующего файла вывода; если файл не существует и перемен-
ная noclobber установлена, возникает ошибка;
>>& - аналогично >&, однако вывод добавляется в конец
файла вывода;
>>! - аналогично >>, однако, если файл вывода не сущест-
вует, он создается (ошибки не возникает);
>>&! - комбинация >>& и >>!
Метасимволы подстановки:
$ - указывает подстановку значения переменной, например:
% set M1 = /usr/man/man3
% cd $M1
! - указывает подстановку команды из буфера истории;
: - указывает подстановку строк в команде из буфера исто-
рии;
? - используется в специальных случаях подстановок команд
из буфера истории.
Прочие метасимволы:
# (диез) - указывает комментарий C-Shell; начинает имена
временных файлов; должен быть первым символом командного
файла в C-Shell;
% - указывает номер процесса, например:
kill %1.
В начало страницы
В добавление к командам языка Shell в C-Shell появился
ряд полезных команд. Рассмотрим некоторые из них.
Команда ls с ключом -F позволяет получить листинг катало-
га с указанием знаком * исполнимых файлов и знаком / катало-
гов.
Пример:
% ls -F
mail help lint1* tabset/
Команда head, симметричная команде tail, позволяет пос-
мотреть на экране заданное количество первых строк файла (по
умолчанию 10 строк), например:
% head -2 people
Mary Clark 101
Sally Smith 113
Листание файла на экране позволяет осуществить команда
more, например:
% more somefile
<первая страница фала>
- - More - - (3 %)
%
Процент в скобках указывает уже просмотренную часть фай-
ла. Для последовательного постраничного просмотра нажмите
клавишу пробела, для построчного - клавишу возврата каретки.
Можно задать начало просмотра со строки с заданным номе-
ром или заданным значением. Примеры:
% more +194 somefile
. . . . .
% more +'more then' somefile
В общем случае значение задается регулярным выражением,
как в ed или grep (см. раздел 10.5).
Команда apropos позволяет найти разделы руководств, ка-
сающиеся заданного ключевого слова.
Пример:
% apropos sort
ddsort (3/21/80) - sort DDBS files
look (1) - find lines in a sorted list
. . . . . . . . . . . . . . .
tsort (1) - topological sort
% man look
<руководство по look (1)>
Просмотреть заголовки руководств можно командой whatis,
например:
% whatis mv ln cp
cp (1) - copy
ln (1) - make links
mv (1) - move or rename files
Команда whereis позволяет найти специальные файлы, свя-
занные с указанной командой (опция -m находит файл руководс-
тва, опция -b - файл кода команды).
Пример:
% wheris -m rm
rm: /usr/man/man1/rm.1
% wheris -b rm
rm: /bin/rm
Команда strings позволяет просмотреть в любом (в том чис-
ле выполнимом) файле все строки (в коде ASCII).
В начало страницы
Выражение, возвращающее значение, зависящее от состояния
файла, используется в условных операторах (см.ниже). Значе-
ние равно единице (1), если выражение истинно, и ноль (0),
если оно ложно или файл не существует.
Синтаксис выражения:
-op <имя файла>,
где op принимает значения:
d - является ли файл каталогом?
e - файл существует?
f - является ли файл простым файлом?
o - это мой собственный файл?
r - имею ли я право чтения файла?
w - имею ли я право записи файла?
x - могу ли я выполнить файл?
z - файл пуст (длина ноль байтов)?
Пример:
if (-d $dir) then
echo "**** $dir is a directory"
В начало страницы
Любая последовательность команд, разделенных метасимвола-
ми ; или |, а также отдельная команда является работой. Каж-
дая работа выполняется отдельным процессом.
Заканчивая такую последовательность команд или отдельную
команду знаком &, можно задать выполнение работы на заднем
плане, то есть параллельно с будущими работами. В этом слу-
чае система сообщает вам номер работы в скобках и номер про-
цесса, например:
% du > usage &
[1] 503
% ls -al
<Содержание текущего каталога>
%.
По окончании работы система сообщает о завершении (нор-
мальном или аварийном), указывая номер работы и процесса,
например:
.....
[1] 503 - Done du > usage
%.
Чтобы посмотреть, какие работы активны в данный момент,
используйте команду jobs -l.
Эта команда распечатает список работ с указанием их сос-
тояния:
Running (выполняется) или Stopped (остановлена).
В начало страницы
Командный файл (скрипт) - это файл, состоящий из команд,
выполняемых группой. Примеры скриптов - файлы .login,.cshrc,
.logout. Прежде чем писать свой скрипт, проверьте UNIX
Reference используемой Вами версии UNIX, нет ли там команды,
уже решающей вашу задачу.
Первый способ выполнения скрипта - ввести команду:
% csh sname arg1 arg2 ...,
где sname - имя скрипта; arg1, arg2 ... - аргументы скрипта.
Аргументы скрипта автоматически помещаются во встроенные
переменные $argv[1], $argv[2] и так далее.
Кроме того, аргументы доступны по ссылкам $n, где n - це-
лое, равное позиции аргумента; $0 означает sname. Различие
между $argv[n] и $n заключается в том, что первая ссылка да-
ет ошибку при выходе значения n за допустимые пределы, а
вторая - нет.
Второй способ выполнения скрипта в C-Shell - обеспечить
его выполнимость (командой chmod) и позаботиться о том, что-
бы он начинался с символа #(диез); в противном случае скрипт
будет выполняться обычным Shell.
Пример:
% chmod a+x sname
% sname arg1, arg2, ...
При выполнеии скрипта производится подстановка значений
переменных, ссылки на которые указывает знак $. Переменная
должна обладать значением в момент ссылки на нее, иначе воз-
никает ошибка.
Узнать, присвоено ли значение переменной, можно с помощью
выражения $?<имя> (1 - присвоено, 0 - нет), а количество
компонентов значения дает выражение $#<имя>.
На компоненты значения можно ссылаться выражением
$<имя>[n], где n - номер компоненты. Компоненты значения
разделяются пробелами, а многокомпонентное значение заключа-
ется в скобки.
Пример:
% set sum1 = (a b c)
% echo $?sum1
1
% echo $#sum1
3
% echo $sum1[2]
b
% unset sum1
% echo $?sum1
0.
Другими полезными подстановками, начинающимися знаком $,
являются:
$* - эквивалентно $argv;
$$ - номер процесса; поскольку он уникален в системе, его
удобно использовать для генерации уникального имени времен-
ного файла;
$< - заменяется строкой последующего ввода со стандартно-
го ввода (клавиатура терминала), что очень полезно при напи-
сании интерактивных скриптов.
Пример:
echo "yes or no?"
set a = ($<)
На экране высветится запрос (yes or no?), затем будет
прочитан ответ и присвоен переменной a.
В начало страницы
Допускается использование выражений над переменными по
правилам операций в языке C. Например, операции '==' и '!='
сравнивают строки, операции '&' и '|' реализуют булевские
операции 'и' и 'или' и так далее. Введены также специальные
операции '=~' и '!~', подобные операциям '==' и '!=', однако
в правой строке допускаются метасимволы C-Shell (*, ? и []).
Кроме того, допустимы выражения для оценки состояния фай-
ла (см. раздел 8.13).
Результат выполнения предыдущей команды (нормальное или
аварийное завершение) можно получить в виде значения пере-
менной
$status (ноль - без ошибок, не ноль - авария).
Допустимые в C-Shell управляющие структуры взяты из языка
C. Напомним, что скрипт в C-Shell должен начинаться с симво-
ла #(диез). Этим же символом вводится комментарий, продолжа-
ющийся до конца строки.
В начало страницы
Оператор цикла foreach имеет синтаксис:
foreach <индекс> (<список значений индекса через пробелы>)
<команда 1>
<команда 2>
..........
end.
Все команды выполняются для каждого значения индекса из
списка значений.
Внутри цикла можно использовать команду break для прекра-
щения выполнения цикла и команду continue для преждевремен-
ного прекращения одной текущей итерации.
При выходе из цикла индекс имеет значение последнего эле-
мента из списка значений.
В начало страницы
Условный оператор имеет синтаксис:
if (<выражение>) then
<команда 1>
<команда 2>
..........
else
<команда A>
<команда Б>
..........
endif
Если альтернатива else пуста (команды А, Б, ... отсутс-
твуют), else можно опустить. Реализация C-Shell требует,
чтобы if и then были обязательно на одной строке.
Допустимы вложенные условные операторы, например:
if (<выражение 1>) then
<команда 1>
..........
else if (выражение 2> then
<команда А>
..........
else
<команда X>
..........
endif
endif
Если в первой альтернативе только одна команда, допуска-
ется следующий синтаксис:
if (<выражение>) <команда 1>
или: if (выражение>\
<команда>
где символ \ должен предшествовать символу перевода ка-
ретки.
В начало страницы
Оператор цикла while имеет синтаксис:
while (<выражение>)
<команда 1>
<команда 2>
..........
end.
Внутри цикла допустимы операторы break и continue
(см.foreach).
Оператор выбора имеет синтаксис:
switch (<переменная>)
case <значение 1>:
<команды>
........
breaksw
case <значение 2>:
<команды>
........
breaksw
........
case <значение n>:
<команды>
........
breaksw
default:
<команды>
........
breaksw
endsw
В отличие от аналогичного оператора в языке C здесь ис-
пользуется специальный оператор breaksw для выхода из аль-
тернативы.
Выполнение осуществляется следующим образом: значение пе-
ременной сравнивается последовательно со значениями 1, 2,
..., n, и выполняются команды первой из альтернатив, для ко-
торых значения совпали. Если таких значений не оказалось,
выполняются команды из альтернативы по умолчанию (default).
В начало страницы
Допускаются метки операторов и оператор goto.
Например:
loop:
<команда 1>
<команда 2>
..........
goto loop
В начало страницы
Обеспечение ввода в командах скрипта в C-Shell из потока
символов текста скрипта вместо стандартного ввода (использу-
емого по умолчанию), потребовало введения специального син-
таксиса. Рассмотрим пример скрипта:
#
foreach i ($argv)
ed -$i << 'STOP'
1, $s/wine/water/g
w
q
'STOP'
end
Строка 'STOP', появляющаяся в тексте скрипта дважды, яв-
ляется меткой, ограничивающей текст ввода, и означает, что
стандартный ввод для команды ed заменяется посредством меха-
низма перенаправления (знак <<) вводом текста из файла само-
го скрипта. Ограничитель 'STOP' заключен в кавычки, чтобы
предотвратить подстановку переменных и команды внутри него.
В примере редактор ed выполняет глобальную подстановку всех
вхождений строки wine на строку water (см. раздел 12.4).
В начало страницы
Если ваш скрипт создает временные файлы, вы можете захо-
теть уничтожить их, даже если прерывание скрипта не позволит
вам выполнить скрипт до конца (предполагается, что в конце
скрипта временные файлы всегда уничтожаются).
Для этого вам нужно в начале скрипта выполнить команду
onintr label, где label - произвольная метка, начиная с ко-
торой в вашем скрипте стоят команды, которые будут выполне-
ны, если произойдет прерывание (так как в случае прерывания
C-Shell автоматически выполнит команду goto label, где label
- метка из команды onintr).
При этом вы можете предусмотреть среди выполняемых в слу-
чае прерывания команд в качестве последней команду exit 1,
чтобы обеспечить ненулевое значение переменной $status, сви-
детельствующей о неблагополучном завершении скрипта.
В начало страницы
Данный скрипт выполняет сохранение файлов C-программ, ко-
торые уже сохранялись ранее. Файлы сохраняются в подкаталоге
backup вашего рабочего каталога.
#
foreach i ($argv)
if ($i \ !~ ~/*.c)
then # является ли файл $i файлом С-программы ?
echo файл $i не является файлом С-программы
continue
else
echo файл $i является файлом С-программы
endif
echo check file ~/backup/$i
if (-e ~/backup/$i)
then # находится ли файл $i в подкаталоге backup?
echo файл $i не находится в подкаталоге backup
continue
endif
echo compare two files $i and ~/backup/$i
cmp -s $i ~/backup/$i
if ($status != 0) then
echo новая копия файла $i
cp $i ~/backup/$i
endif
end.
Собственно копирование делается командой cp, а все ос-
тальные строчки скрипта организуют цикл и осуществляют про-
веркия.
|