При интерактивной работе с системой пользователь постоянно сталкивается с необходимостью отдавать ей команды. В CDE это можно делать, выбирая мышью требуемые пункты меню. В текстовом окне или текстовом режиме команды набираются вручную в командной строке. После нажатия Enter команда должна быть интерпретирована и синтаксически проанализирована (где - имя программы, где - ключи, где - аргументы, где - спецсимволы). Затем будут запущены один или несколько процессов.
В UNIX эту работу выполняет программа, которая называется командным процессором (shell). Иногда командный процессор называют шеллом (это - просто калька с английского) или интерпретатором команд (а это - неточно, потому что круг задач командного процессора шире, чем интерпретация команд).
Существует несколько широко распространенных командных процессоров и еще несколько малораспространенных, специфичных для конкретных вариантов UNIX. В Solaris принято использовать ksh, csh или bash.
Первый в мире UNIX командный интерпретатор в 1976 году написал Стив Баурн (Steve Bourne), когда он работал в Bell Laboratories в AT&T. (По другим данным, Стив написал его в 1974 году.) Через некоторое время в University of California Berkeley был написан C-shell (csh, произносится "си шелл"), а потом число разных командных процессоров стало быстро расти. Самыми популярные из них сейчас - это Bourne again shell (bash), разработанный в рамках проекта GNU и Korn shell (ksh) Дэвида Корна (David Korn).
С-shell был разработан студентом Университета в Беркли (University of California Berkeley) Биллом Джоем (Bill Joy), который по окончании Berkeley основал компанию Sun Microsystems. Еще Билл Джой написал самый известный в UNIX редактор vi и был одним из авторов первой версии BSD UNIX.
В конце 1970-х годов был написан tcsh, расширение csh, совместимое с ним по командам, макроопределениям и синтаксису языка скриптов. Кен Грир (Ken Greer) начал работу над tcsh в Университете Карнеги-Мелон (Carnegie-Mellon University), а продолжил ее Пол Плэйсвэй (Paul Placeway) в восьмидесятые годы в Университете Огайо (Ohio State). Основные отличия tcsh от csh сводятся к усовершенствованию редактирования командной строки и ряду дополнений в помощь создателям скриптов (например, переменные среды окружения, создаваемые только для чтения). В последних версиях UNIX csh обычно является символической ссылкой на tcsh, а оригинальный csh в поставку не включается, чтобы не шокировать пользователей пещерным уровнем редактирования командной строки.
В Solaris по умолчанию устанавливаются несколько командных процессоров, в том числе sh, csh, tcsh, bash и другие; командным процессором по умолчанию является sh.
Командный процессор призван выполнять в системе нижеперечисленные задачи:
Некоторые командные процессоры поддерживают не все эти функции (см. таблицу 12.2).
Командный процессор запускается либо при входе пользователя в систему (и в дальнейшем пользователь отдает команды в его командной строке), либо из какой-либо программы (по команде пользователя). Частным случаем является запуск командного процессора из другого командного процессора. Например, вы работаете в sh и желаете получить более удобные средства редактирования командной строки; для этого вызывается bash. Тогда вы просто набираете команду
bash
и оказываетесь в среде свежезапущенного командного процессора bash. При этом обычно меняется вид приглашения командной строки.
Каждый командный процессор при запуске пытается выполнить свои стартовые файлы, вначале системные (общие для всех пользователей), а затем пользовательские. Общие лежат в /etc, индивидуальные - в домашнем каталоге пользователя. Если командный процессор запускается при входе пользователя в систему (в таком случе он называется login shell, дословно - командный процессор, запущенный при входе в систему), то после стартовых файлов он выполняет еще и login-файлы в том же порядке: сначала общий login-файл из /etc, затем - индивидуальный, из домашнего каталога. Login-файлы - это тоже стартовые файлы командного процессора; все стартовые файлы фактически представляют собой скрипты на языке командного процессора и служат для инициализации среды окружения командного процессора для конкретного пользователя. Настройка командного процессора для пользователя позволяет творить чудеса: задать короткие псевдонимы для длинных часто используемых команд и т.п.
Некоторые командные процессоры при входе в систему выполняют сначала login-файлы, а затем - стартовые файлы; это зависит от того, как они были скомпилированы.
Другие командные процессоры не выполняют никакие стартовые файлы иначе, как при входе пользователя в систему. У командного процессора обычно есть ключ, который можно дать, чтобы сымитировать вход в систему и заставить его выполнить login-файлы.
Командный процессор bash, в отличие от других, использует более сложный алгоритм выполнения стартовых и login-файлов. Если он запущен как login shell, то выполняет /etc/profile, если такой файл есть. Затем делается попытка выполнить ~/.bash_profile. Если такого файла нет, bash пытается выполнить файл ~/.bash_login, а если нет и такого файла, то выполняется ~/.profile. Если bash запущен не как login shell, то при старте он выполняет только файл ~/.bashrc. Если же bash был запущен как sh (т.е. 9sh является символьной ссылкой на bash ), то при старте он ведет себя так же, как и sh.
Все командные процессоры запоминают введенные пользователем команды (их список называется историей команд). Во время сеанса работы командный процессор хранит историю команд в памяти, а по окончании работы записывает их в файл на диск. Файл истории команд хранится в домашнем каталоге пользователя. В sh, csh, tcsh он называется ~/.history, в bash - ~/.bash_history, в ksh - ~/.shhistory, а в бесплатной версии Korn Shell (public domain Korn shell - pdksh) его по умолчанию нет вообще.
Многие командные процессоры позволяют повторить вызов ранее введенной команды по ее номеру или начальным буквам. О том, как это делать, подробнее рассказано ниже в разделе "повторение ранее введенных команд".
Существование файла истории команд может привести к уязвимости вашей системы. Имейте в виду, что по умолчанию он может быть доступен для чтения не только тому, кто вводил команды, но и другим пользователям. В этом случае следует избегать ввода каких бы то ни было паролей в командной строке. Например, возможно вызвать веб-обозреватель lynx или программу доступа к серверу баз данных mysql, указывая пароль в командной строке:
lynx ftp://user:password@URL mysql -u root -p password
Так как эти команды сохранятся в файле истории вместе с другими, кто-то потом сможет прочесть их и узнать некоторые из ваших паролей.
Файл истории команд ограничен по размеру. По умолчанию, bash хранит 500 команд, tcsh - 1000, csh - 100, sh - в зависимости от версии. Часто sh не создает файл .history вовсе и дает доступ только к командам, которые были введены в течение текущего сеанса работы с ним. Можно изменить число хранимых команд, указав иное значение переменной, в которой оно хранится.
shell | Переменная | Значение по уполчанию |
---|---|---|
sh | HISTSIZE | не определено |
csh | history | 100 |
ksh | HISTSIZE | 128 |
bash | HISTFILESIZE | 500 |
Как отмечалось раннее, каждый процесс имеет свою среду окружения - специальную область, в которой хранятся имена переменных и их значения. Для использования значения переменной в командном процессоре надо применять конструкцию
$имя_переменной.
Например, echo $TERM выведет на экран значение переменной TERM. Пользователь может определить свои собственные переменные. Новая переменная появляется, как только вы даете команду присвоить значение несуществующей переменной. Переменная не имеет типа, так как считается, что все переменные имеют тип "строка". При этом если попытаться выполнить арифметическую операцию с переменными, имеющими значение неких чисел, то такая строка будет преобразована в число, число использовано в операции и результат преобразован обратно в строку.
Попробуйте
$i=2 $j=3 expr $i \* $j
Присвоение переменной значения во всех командных процессорах, кроме csh, выполняется командой
VAR=value
set VAR=value
или
setenv VAR value
Переменные со специальными названиями типа DISPLAY, TERMINFO и т.п. используют программы, которые проверяют свою среду окружения на наличие таких переменных и их значений. Поведение таких программ может изменяться в зависимости от значения переменных.
Переменные могут экспортироваться, т.е. передаваться от процессов-родителей процессам-потомкам. Для экспорта переменной надо дать команду
export имя_переменной
Если надо удалить переменную среды окружения, можно присвоить ей пустое значение (это не равнозначно удалению, но иногда этого достаточно), а можно удалить ее вовсе командой unset.
В tcsh есть возможность создавать переменные только для чтения, без права изменения значений: для этого служит команда
set -r имя=значение.
Кроме этого, в tcsh можно присвоить переменной значение в виде списка слов, к которым потом можно обращаться по номеру слова, начиная с 1:
set var=(hello world) echo {$var[1]} hello echo {$var[2]} world
Для вывода на экран списка всех переменных с их значениями надо дать команду set без параметров.
Предопределенные переменные содержатся в среде окружения командного процессора независимо от установок, которые может сделать пользователь в стартовых скриптах. Имена предопределенных переменных среды окружения во всех командных процессорах, кроме csh (и, в некоторых случаях, tcsh) пишутся символами верхнего регистра: PATH, USER, TERM, PS1, PS2.
В именах переменных среды окружения используются буквы латинского алфавита. Принято пользовательские, добавленные по ходу работы переменные в скриптах называть именами из символов нижнего регистра для того, чтобы отличать переменные, введенные разработчиком системы, от тех, что вводит пользователь или требует прикладная программа.
В любых командных процессорах обязательно заранее определены переменные перечисленные в таблице 12.5.
С другой стороны, многие другие переменные определяются не во всех командных процессорах. Посмотреть список всех переменных среды окружения обычно можно по команде
set
Любой скрипт может быть вызван с аргументами, которые в скрипте называются позиционными параметрами. К аргументам с первого по девятый следует обращаться как к $1..$9. Значение $0 - это имя самого скрипта, по которому его вызвали. Один и тот же скрипт может быть вызван с разными именами, например, если с ним установлены символи- ческие связи (symbolic links).
Команда shift n (n - положительное или отрицательное смещение) позволяет двигать "окошко" $1..$9 по всему массиву аргументов скрипта вперед и назад, если аргументов больше девяти. Shift без параметров эквивалентен shift 1. В csh "окно" умеет сдвигаться только на одну позицию вперед.
Кроме вышеописанных переменных обычно определены переменные перечисленные в таблице 12.6
Переменная | Смысл |
---|---|
$ | Номер процесса текущего shell'a |
* | Все позиционные параметры |
_ | Последняя вызванная команда |
1,2,..9 | Один позиционный параметр |
$# | Число позиционных параметров |
При запуске программ из командной строки часто требуется передать им в качестве аргументов одно или несколько имен файлов. Часто эти имена удобно задать шаблоном - например, /var/log/messages.?, что означает "все файлы из каталога /var/log, имена которых начинаются на messages., а завершаются любым символом". Любой командный процессор умеет подставлять в командную строку имена файлов, соответствующие шаблону:
ls -l /var/log/messages.?
Символ "?" трактуется командным процессором как шаблон, которому соответствует один любой символ.
Обратите внимание на то, что командный процессор не понимает регулярных выражений. Его шаблоны похожи на регулярные выражения, но это - две совершенно разные песни. Для обработки регулярных выражений в любом приложении используется стандартная функция regex, а шаблоны имен файлов каждый командный процессор обрабатывает по-своему.
Командный процессор распознает и интерпретирует следующие символы в шаблонах (такие символы называются метасимволами, metasymbols или wildcards).
Метасимвол | Смысл |
---|---|
* | Любая подстрока, в том числе пустая. |
? | Один любой символ. |
[...] | Один любой символ из списка (например, [avgf]) или диапазона (например, [a-z]) |
Порядок подстановки имен файлов по шаблону таков: вначале командный процессор находит все файлы, имена которых соответствуют шаблону, а затем подставляет имена всех этих файлов через пробел в строку в то место, где был написан шаблон.
Стало быть, если в текущем каталоге есть файлы money.c, money.bak, money.obj и wallet.x, то команда
ls -l money.*
будет раскрыта в
ls -l money.c money.bak money.obj
Иногда возникает необходимость отыскать в системе файлы по некоему признаку и со всеми этими файлами выполнить одинаковое действие: например, во всех файлах *.html заменить подстроку Siemens на Nixdorf. Если это требуется сделать только для файлов, лежащих в одном каталоге, то задача решается достаточно просто. Здесь мы приведем пример скрипта для Bourne Shell, но аналогичный скрипт легко написать и для других командных процессоров:
for i in *.html do sed 's/Siemens/Nixdorf/g' <$i >tmp mv tmp $i done
Переменная i последовательно принимает значения из списка, т.е. на каждой итерации цикла она имеет разное значение; список будет содержать имена всех файлов текущего каталога, соответствующих шаблону *.html.
Команда sed обеспечивает замену всех вхождений Siemens на Nixdorf, причем во входной поток sed перенаправляется содержимое очередного файла, в зависимости от значения переменной i. Результат направляется в файл tmp, а команда mv обеспечивает переименование файла tmp в нужное имя для замены старого файла из списка *.html новым.
Что делать, если такую процедуру надо проделать со всеми файлами *.html всего дерева каталогов, начиная с текущего каталога?
В UNIX есть уникальная возможность, которая реализована в любом командном процессоре: можно "вложить" одну команду в другую так, чтобы вначале выполнилась первая, а затем результат ее выполнения был подставлен в командную строку для вызова второй команды.
Итак, мы хотим найти все файлы *.html в поддереве файловой системы, начиная с текущего каталога.
find . -name "*.html"
Теперь воспользуемся конструкцией "подстановка результата выполнения" и перепишем наш скрипт для замены подстрок:
for i in ` find . -name "*.html" ` do sed 's/Siemens/Nixdorf/g' <$i >tmp mv tmp $i done
Команда, заключенная в ` ` (обратные апострофы), выполняется первой, а результат ее выполнения подставляется в командную строку. Затем командная строка запускается на выполнение.
Функция "подсказки" (можно сказать также - "завершения") имен файлов (file name completion) позволяет набрать только часть имени существующего файла и затем нажать клавишу <Tab>. В ответ на это командный процессор "закончит" набор имени файла. Например, если надо обратиться к файлу /usr/sadm/admin/bin/printmgr, то достаточно набрать
/usr/sa<Tab>dm/a<Tab>dmin/b<Tab>in/pr<Tab>intmgr
Завершение имен файлов реализовано только в bash и tcsh.
Тем, в чьей системе есть файлы с длинными уникальными именами, подсказка имен файлов отлично экономит время.
При двойном нажатии <Tab> выводятся все возможные варианты завершения имени файла.
Например, если в каталоге есть два файла, начинающиеся с букв msg: msg01.txt и msg02.txt и надо просмотреть один из них, я набираю more msg<Tab><Tab>
Командный процессор bash (или tcsh) мне подскажет:
msg01.txt msg02.txt
Теперь достаточно набрать еще цифру 1 или 2, чтобы указать, какой именно файл требуется, и еще раз нажать <Tab> для окончательного завершения имени. Если после двойного нажатия <Tab> bash видит слишком много возможных вариантов имен, он спросит:
There are 1102 possibilities. Do you really wish to see them all? (y or n)
Стоит ответить n: так много имен не уместится на экран.
Редактировать командную строку приходится для того, чтобы исправить что-то в только что набранной строке. В sh нельзя передвинуть курсор в любую позицию в строке, в остальных командных процессорах - можно. Удобнее всего редактировать командную строку в bash.
В каждом командном процессоре реализованы стирание последнего символа клавишей <backspace> и стирание строки целиком комбинацией клавиш <Ctrl-U>.
В самых первых реализациях командных процессоров средства редактирования были еще более примитивными (например, удаление всей строки целиком выполнялось вводом @ и последующим вводом строки заново, при этом все набранные символы все равно оставались на экране). Сейчас такие архаические приемы редактирования не применяются ни в одном командном процессоре.
В bash и tcsh можно перемещаться вперед и назад по уже введенным символам в строке с помощью "стрелок", вводить знаки в середину и в начало строки. Командный процессор bash после нажатия Enter принимает всю строку целиком, независимо от того, в какой позиции строки находился курсор при нажатии Enter. Например, можно вернуть курсор к середине строки, если ввод оказался неверным, исправить ошибку и тут же нажать Enter, чтобы запустить команду на выполнение. В некоторых старых версиях командных процессоров в этом случае следует исправить строку, перейти к ее концу для ввода команды и только после этого нажать Enter.
В ksh редактирование по умолчанию выключено, его надо включить нажатием клавиши Esc4Редактирование командной строки будет работать корректно, только если терминал настроен правильно, а значение переменной среды окружения TERM совпадает с реальным типом терминала.. После этого командная строка будет редактироваться командами того редактора, имя которого задано в переменной среды окружения VISUAL или EDITOR. По умолчанию это редактор vi. Трудно найти такого системного администратора, которому такой громоздкий и неудобный способ исправления команд покажется удачным: ведь ко всему прочему ему придется помнить о переключении режимов редактирования строки ввода!
Бывает удобно повторить команду, которую вы недавно уже вводили; особенно это помогает при вводе длинных команд с одинаковыми аргументами. Иногда повторяемая команда должна немного отличаться от оригинала, тогда следует модифицировать запись о ранее введенной команде и запустить на выполнение свежий вариант.
Например, введя
lyxn -p proxy.spb.edu:3128 www.macropulos.cam.ac.uk
вы получаете в ответ "command not found", потому что вы собирались запустить lynx, но допустили опечатку в имени программы. Не повторять же теперь ввод всей длинной строки! Если бы опечатка была в конце строки, можно было бы вызвать строку с предыдущей командой клав- шей "стрелка вверх", но здесь опечатка в начале строки, и после вызова выполненной строчки придется еще двигать курсор в ее начало. Есть более короткий вариант, доступный в csh, tcsh и bash:
^xn^nx
Эта конструкция требует у командного процессора повторить предыдущую команду, заменив первой вхождение подстроки xn на nx. И это все!
В csh, tcsh, bash есть и другие средства модификации командной строки. Они перечислены ниже:
Командные процессоры csh и tcsh по-разному интерпретируют конструкцию !nstr, например, `!67r'. Для csh это - команда номер 67, в конец которой добавляется r перед выполнением, а для tcsh это - последняя начинающаяся на 67r команда. Такой синтаксис введен в tsch для удобства повторения команд, чьи имена начинаются с цифр. Чтобы заставить tcsh вести себя подобно csh, нужно перед числом поставить обратный слэш, экранирующий его специальное значение: `!\6\7r'.
В bash повторение команд выполняется так же, как и в csh. Дополнительно можно использовать клавиши "вверх" и "вниз" для переходов между командами, введенными раньше или позже.
В ksh для повторения команд используют встроенную команду r, а в sh - команду fc, при этом в sh можно вызвать только такую команду, которая была введена в текущем сеансе, потому что sh не ведет файл истории.
Кроме этого, в bash можно вызвать встроенный интерактивный поиск в истории команд, нажав <Ctrl-R> и затем введя подстроку для поиска; найденная команда отобразится автоматически.
При работе в командной строке вы можете запустить несколько программ одновременно, например, организовав конвейер. Совокупность таких процессов, одновременно запущенных из среды командного процессора, называется заданием.
Задание можно приостановить, потребовать его продолжения или завершить его. Задание может выполняться как в фоновом режиме, так и в интерактивном. Для управления заданиями большинство командных процессоров (точнее, все кроме Bourne Shell) имеют встроенные команды: jobs, fg, bg.
Посмотреть список запущенных ранее заданий можно с помощью команды jobs. Для вывода идентификаторов (PID) процессов, входящих в задание, следует использовать команду
jobs -l.
Например, запускаем программу find для поиска файлов *.gif, список найденных файлов перенаправляем в ~/gifs (т.е. наш домашний каталог, файл gifs ):
find / -name "*.gif" > ~/gifs & [1] 33151 jobs -l [1]+ 33151 Running find / -name "".giff" > ~/gifs &
То, что указано в квадратных скобках [ ], и есть номер задания. Задания имеют уникальные номера в пределах текущего сеанса работы с shell'ом. Задание можно перевести в интерактивный режим командой fg (foreground):
fg %1 # %1 - номер задания
Теперь задание выполняется в интерактивном режиме. Можно остановить его, переведя в режим suspend (sleeping, спящий):
<Сtrl-z> [1]+ Stopped find / -name "".giff" > ~/gifs
Теперь можно продолжить выполнение задания в фоне командой bg (background):
bg %1
С помощью команд управления заданиями можно переключать программы между интерактивным и фоновым режимом выполнения. Если вы случайно забыли поставить знак & в конце команды, но собирались запустить ее в фоновом режиме, еще не все потеряно! Следует нажать Ctrl-Z, чтобы "усыпить" программу, а затем запустить задание в фоновом режиме с помощью команды bg.
Аргументы команд bg и fg в разных командных процессорах могут выглядеть по-разному. Однако, знак процента %, за которым указывается номер задания, все командные процессоры интерпретируют одинаково: как ссылку на номер задания.
Существует всего два типа языков, которые используются в командных процессорах. Это sh -подобный язык и csh -подобный язык. Первый тип поддерживается в sh, ksh, bash. Второй - в csh и tcsh. Язык sh более удобен и стандартен, на нем написаны практически все скрипты во всех системах UNIX, включая стартовые скрипты системы. Язык csh по синтаксису ближе к языку программирования С, но используется для скриптов реже. Однако, в некоторых случаях программное обеспечение включает в себя скрипты на языке csh, поэтому здесь мы разберем вкратце конструкции обоих языков.
Первой строкой любого скрипта должна быть строка, содержащая управляющий комментарий специального вида:
#!полное_имя_командного процессора
например
#!/bin/sh
Этот комментарий требует выполнить скрипт с помощью указанного командного процессора. По умолчанию скрипт выполняется в среде /bin/sh, даже если он запущен в среде другого командного процессора. Если вы работаете в tcsh и желаете, чтобы ваши скрипты запускались в tcsh, следует обязательно указать полный путь к tcsh в управляющем комментарии.
В языке sh существуют операторы ветвления и циклов. Ниже дано описание этих операторов. В нем жирным шрифтом выделены ключевые слова. Конструкция "команды" подразумевает одну или несколько команд командного процессора или вызовов программ, которые отделяются друг от друга разделителями (точкой с запятой или переводом строки). При вводе многострочных операторов в командной строке командный процессор начинает новую строку приглашением "продолжение команды" (его вид определяется значением переменной среды окружения PS2 или prompt2).
В операторах циклов допустимы команды break (прерывание цикла, управление передается за конец цикла) и continue (передача управления на начало цикла, переход к следующей итерации). Эти команды действуют одинаково в любых командных процессорах, так как они реализованы и в языке sh, и в языке csh.
if условие then команды else команды fi
В bash, ksh и новых версиях sh возможна конструкция elseif (вложенное ветвление):
if условие then команды elseif условие then команды fi else команды fi case значение_переменной of значение1) команды; break; значение2) команды; break; значение3) команды; break; *) команды; esac
Знак "звездочка" (*) означает "все остальные значения", т.е. если значение переменной не равно ни значению1, ни значению2, ни значению3.
Операторы цикла while (выполнять, пока условие истинно) и until (выполнять до тех пор, пока условие станет истинным):
while условие do команды done until условие do команды done
Все эти операторы содержат неотъемлемый элемент, обозначенный нами условие. Это - любая команда (в том числе другой скрипт или конвейер), возвращающая код завершения.
Условие считается истинным, если код завершения равен нулю, и ложным - если код завершения не равен нулю. Любая команда в UNIX возвращает код завершения, нулевой - в случае успешного выполнения и ненулевой - в противном случае. Значения кодов завершения программ можно выяснить с помощью руководства к ним, например, man.
Для проверки условий, относящихся к объектам файловой системы, есть программа test. В некоторых командных интерпретаторах есть встроенная команда test, в других системах test - это отдельная программа. С помощью test часто проверяется наличие файла или каталога в файловой системе:
if test -e имя_файла then echo "файл существует!"
Язык sh допускает конструкцию [ ] вместо команды test:
if [ -e имя_файла ] then echo "файл существует!"
Эта конструкция эквивалентна вышеприведенной.
С помощью test и [ ] можно проверять различные условия, полный список которых можно почерпнуть из man test или man sh, man bash.
Некоторые программы всегда возвращают код завершения ноль. Это легко использовать для организации бесконечных циклов. Такие циклы могут понадобиться для перезапуска процессов, имеющих тенденцию к неожиданному и ненужному завершению. Например, так можно запускать процесс pppd для соединения с провайдером по выделенной или коммутируемой линии:
while sleep 10 do /usr/sbin/pppd done
Программа sleep всегда будет возвращать ноль, так что цикл никогда не прервется и будет исправно запускать pppd всякий раз, как только он завершится, например, из-за ошибки связи. Десять секунд ожидания добавлены просто для того, чтобы было время переждать неблагоприятную ситуацию, из-за которой произошла ошибка.
В Solaris и других системах System V такое применение менее полезно, чем в BSD-системах, так как того же эффекта можно добиться, написав вызов pppd в /etc/inittab с указанием режима запуска respawn (запустить, если завершится).
Оператор for (цикл повторяется для каждого значения из списка):
for имя_переменной in список do команды done
Оператор цикла for используется особенно часто, например, для однотипной модификации нескольких файлов сразу. Предположим, надо во всех файлах *.html в текущем каталоге изменить ссылку на файл с фотографией:
for i in *.html do sed 's/otello.gif/dezdemona.gif/g' <$i>tmp mv -f tmp $i done
Поскольку sed не меняет файл, а лишь выдает измененный текст в свой выходной поток, приходится перенаправлять вывод во временный файл tmp (назовите ваш по вкусу, от названия ничего не зависит) и затем переименовать tmp в файл с тем же именем, что у исходного файла. В момент переименования старый файл, естественно, исчезнет.
При вызове sed: следует писать именно $i, а не просто i, чтобы командный процессор подставил в командную строку значение переменной i, а не символ i.
Сразу перенаправить вывод в файл, имя которого указывается как $i, нельзя, поскольку перенаправление вывода в существующий файл вызовет уничтожение его прежнего содержимого. Это значит, что одновременное перенаправление ввода и вывода из/в один и тот же файл недопустимо.
Программе mv дается ключ -f, который требует от нее выполнить работу, не задавая вопросов типа "а Вы действительно хотите уничтожить файл?"
Для вывода информации в sh принято использовать команду echo. Эта команда печатает в стандартный выходной поток свои аргументы, а в конце вывода выполняет перевод строки.
Команда
echo -n строка
выводит строку и не добавляет перевод строки в конце.
Для ввода информации в скриптах на языке sh используют оператор read:
read name echo "Name is $name"
Язык, реализованный в вашем командном процессоре, может быть богаче, чем описанный здесь минимальный стандарт. Для получения дополнительной информации обратитесь к man по вашему командному процессору
В операторах циклов языка csh можно использовать команды break (прерывание цикла, управление передается за конец цикла) и continue (передача управления на начало цикла, переход к следующей итерации) так же, как и в языке sh.
Языки sh и csh отличаются синтаксисом операторов и некоторыми командами. Помните, что:
В csh и tcsh есть свои правила вычисления логических выражений, чтобы выяснить истинность или ложность условия в операторах цикла и ветвления. Команда test есть в любом языке, независимо от командного процессора.
if (условие)команда
или
if (условие) then команды else if (условие) then команды else команды endif
Допускается любое число вложенных операторов elseif, при этом нужен только один оператор endif.
Отступы в операторе ветвления не важны, но операторы else и endif должны начинаться с новой строки, оператор if должен следовать за else или начинаться с новой строки.
Оператор множественного ветвления в csh называется switch:
switch (строка) case строка1: команды breaksw case строка2: команды breaksw default: команды breaksw endsw
Опреатор switch в csh выполняется подобно оператору switch из языка С, команда breaksw передает управление за оператор endsw.
Оператор while действует так же, как while в sh, однако синтаксис у него немного иной:
while (условие) команды end
Оператор цикла for в csh назвали foreach, подобно одноименому оператору из Perl:
foreach имя_переменной (список) команды end
Если оператор foreach вводится в командной строке, то csh на каждой новой строке выводит приглашение "foreach?". Это означает, что ввод оператора еще не закончен и его можно продолжать, ввод завершается финальным словом end в начале строки.
Для ввода информации в скриптах на языке sh используют конструкцию $< (подстановка строки из входного потока):
echo " Enter your name:" setenv name $< echo "Name is $name"
Командный интерпретатор имеет несколько вариантов приглашений на разные случаи жизни.
По умолчанию в sh - это $, в csh - %. Привилегированный пользователь (root) имеет другое приглашение - #.
В среде окружения каждого командного процессора есть переменные PS1 и PS2. Это - вид обычного приглашения и приглашения к продолжению ввода команды соответственно.
При вводе длинной команды можно набрать ее в две строки, для этого следует в конце первой строки набрать символ обратного слэша и нажать Enter - вот так:
\<Enter>
и продолжить ввод на следующей строке. Команда может быть и еще более многострочной; как правило, допустимая длина команды составляет 1024 символа. Обратный слэш экранирует следующий за ним символ перевода строки от интерпретации в качестве символа завершения команды. При переходе к новой строке появится символ >, так как именно это значение по умолчанию имеет PS2.
В csh и tcsh вместо PS1 и PS2 определены переменные prompt и prompt2. Некоторые командные процессоры, в частности, ksh, имеют дополнительные приглашения для специальных случаев. Они хранятся в переменных PS3, PS4 и т.д., а в csh - в prompt3 и prompt4.
Многие реализации командных процессоров (прежде всего, bash ) умеет показывать приглашения, включающие в себя динамически подставляемые части (например, имя текущего каталога). В этих командных процессорах есть свои собственные макроопределения для таких подстановок. Например, имя текущего каталога в bash подставляется в приглашение командной строки с помощью макроса \w, а в csh - %/. Помните, что назначать желаемое значение переменной можно, только указывая макрос внутри апострофов, чтобы экранировать его от интерпретации командным процессором, например, в bash:
$PS1='\w$'
Перечень макроопределений для приглашений командной строки обычно содержится в руководстве man по командному интерпретатору.
Как вы уже знаете, все командные процессоры воспринимают некоторые символы как служебные, придавая им специальное значение при разборе командной строки. Выше рассматривались спецсимволы, связанные с указанием конкретных конструкций. Уже было показано, что многие служебные символы интерпретируются разными командными процессорами одинаково, хотя некоторые - по-разному. Основные спецсимволы приведены в табл. 12.8.
Для ввода специальных символов без учета их специального смысла (например, для вычисления произведения двух чисел выполняется команда expr 2 \* 2, надо передать программе expr просто звездочку, не расшифровывая ее специальное значение для командного процессора) в командной строке предваряйте их символом экранирования \ либо заключайте в кавычки или апострофы. Кавычки отличаются от апострофов тем, что экранируют от интерпретации все специальные символы, за исключением `, $ и \, а апострофы экранируют абсолютно все специальные символы.
Каждый командный процессор выполняет разбор командной строки строго в следующем порядке:
Командные процессоры csh и tcsh кэшируют в сразу после начала работы список выполняемых файлов из каталогов, указанных в переменной path, поэтому при изменении значения этой переменной или при добавлении новых исполняемых файлов в указанные в ней каталоги следует выполнять команду rehash, чтобы командный процессор обнаружил новые каталоги и команды. Без этой команды новые программы будут недоступны, их придется вызывать по полному имени файла.