| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
Интерактивные интерфейсы пользователей
Командные интерпретаторы Командные интерпретаторы Командный интерпретатор (по-другому - оболочка, shell) в операционных системах семейства UNIX предназначен для выполнения в основном следующих функций:
В системах UNIX (и во FreeBSD естественно) имеются несколько различных командных интерпретаторов. Наиболее популярные из них:
Как правило, все shell находятся в каталоге /bin. Но это не обязательно. Вы помните, что когда мы рассматривали вопросы установки packages, то установили интерпретатор bash в каталог /usr/local/bin. Все установленные в системе оболочки перечислены в файле /etc/shells. Наберите команду cat /etc/shells, и вы увидите примерно следующее: /bin/sh /bin/csh /usr/local/bin/bash Если строка в файле, в котором записаны команды интерпретатора, начинается на # , то эта строка - комментарий. Это не относится к самой первой строке файла. Она должна содержать запись, типа #!/bin/sh. Это указывает, что для выполнения команд будет вызван интерпретатор /bin/sh. Далее рассмотрим возможности и языки командных интерпретаторов. Базовые возможности командных интерпретаторов Для определенности, в данной главе будем рассматривать интерпретатор bash. Если вам больше нравится работать и программировать в другой оболочке, можете в принципе пропустить изучение этой главы курса. Но замечу, что базовые возможности разных оболочек примерно одинаковые. Переменные и подстановка значений Все переменные в языке shell - текстовые. Их имена должны начинаться с буквы и могут состоять из латинских букв, цифр и знака подчеркивания (_). Bash поддерживает как простые переменные, так и массивы. Для установки переменной используется оператор =: Для простых переменных <имя>=<значение> Для массивов <имя>[индекс]=<значение>, либо <имя>=(<значение1> <значение2> : <значениеN>), либо <имя>=([индекс1]=<значение1> [индекс2]=<значение2> : [индексN]=<значениеN>) Чтобы воспользоваться значением переменной, надо перед ней поставить символ $. Можно также заключить переменную в фигурные скобки {}. Например: # hour=14 # echo $hour 14 # hourth=24 # echo $hourth 24 # echo ${hour}th 14th Двойные кавычки ( " ), одиночные кавычки ( ' ), обратные кавычки ( ` ) Кавычки могут использоваться для создания строк. Например: "Hello, world!" 'Good bye' Кроме того, кавычки могут отменять действие следующих специальных символов: ` ~ ! # $ % ^ & * ( ) - + = \ | ; ' " , . < > ? Значения этих специальных символов в строках, заключенных в одиночные кавычки '<строка>' отменяются. В строках, заключенных в двойные кавычки "<строка>" также отменяются значения специальных символов, за исключением ! $ ` \ {. Обратная наклонная черта \ также отменяет действие специальных символов. Не путайте одиночные и обратные кавычки. Пример: # dat=`date` (здесь стоят обратные кавычки) # echo $dat Mon Jun 05 14:17:20 2000 # dat='date' (здесь стоят одиночные кавычки) # echo $dat date Конвейеры и списки Несколько команд могут быть объединены с помощью символов канала |. В этом случае они образуют конвейер. <команда1> | <команда2> | <команда3> : Символ канала | соединяет стандартный вывод команды <команда1> со стандартным вводом команды <команда2> и т.д. Каждая команда выполняется в отдельном процессе, а состояние выхода последней команды будет являться состоянием выхода конвейера. Примеры: # ps -ax | more # ls -l | grep "profile" Кроме конвейеров, команды могут объединяться в списки. Даже сами конвейеры могут быть объединены в списки. Это делается с помощью команд ; && ||. Команда ; просто последовательно выполняет оду команду или конвейер за другой (другим): # make depend ; make ; make install # cat /etc/passwd | grep root ; echo "User root" Для того, чтобы управлять выполнением следующей команды в списке в зависимости от состояния выхода предыдущей, используются команды && (логическое И) и || (логическое ИЛИ). Примеры: # mkdir mydir && cd mydir В этом случае команда cd mydir будет выполнена только в том случае, если успешно (состояние выхода равно 0) завершится команда mkdir mydir. # cat /home/bob/.profile || echo "Нет файла .profile" В этом случае либо на экран будет выведено содержимое файла /home/bob/.profile, либо сообщение о том, что такого файла нет. Перенаправление ввода-вывода Команды и списки могут содержать операторы < и > - перенаправления стандартного ввода и стандартного вывода соответственно. Например: # ps -ax > /etc/proc выводит текущее состояние процессов не на экран, а в файл /etc/proc. Если к этому моменту такого файла не было, то он будет создан. Если он существовал, то его старое содержимое будет уничтожено новой информацией. Для то, чтобы не уничтожать содержимое файла, а добавить новую информацию (в конец файла), нужно использовать оператор `>>: # ps -ax >> /etc/proc Кроме того, существует стандартный вывод ошибок. Он имеет дескриптор 2. Т.е. если мы не хотим получать сообщения об ошибках на стандартный вывод, то можно использовать перенаправление таким образом: # cat /etc/proc 2>err.log (ошибки, если возникнут, будут выведены в файл err.log) либо # cat /etc/proc 2>/dev/null (ошибки будут выведены <никуда>, их посмотреть будет невозможно). Ввод перенаправляется аналогичным образом. Например, команда # mail bob@com.com < /home/mail.txt отправит содержимое файла /home/mail.txt по адресу bob@com.com. Оператор << означает, что ввод для данной команды находится <ЗДЕСЬ>. Пример: # mail bob@com.com << end Hello, Bob! end По этой команде в тело письма войдет все, что встретится до указанного нами ограничителя ввода end. Управление ходом выполнения. Циклы Управлять ходом выполнения сценария на языке bash можно, используя кострукцию операторов if-fi. Оператор if имеет вид: if <условие 1>; then <список операторов 1> elif <условие 2>; then <список операторов 2> else <список операторов 3> fi Работает эта конструкция так: Если выполнено <условие 1>, то выполняется <список операторов 1>. Если невыполнено <условие 1>, но выполнено <условие 2>, то выполняется <список операторов 2>. Если невыполнено <условие 1> и невыполнено <условие 2>, то выполняется <список операторов 3>. В конструкции if-fi операторы elif и else являются необязательными. В качестве условия проверки может быть использована любая команда (или список команд). Тогда условие будет считаться выполненным, если команда (список команд) завершилась с кодом 0 (т.е. выполнилась нормально). Но на практике чаще используют команду test для проверки какого-либо выражения. Команда test записывается так: test <выражение> или же [<выражение>]. Ниже приводится список опций, используемых при выполнении команды test.
Пример: if [ -x /usr/games/pool ] ; then /usr/games/pool else echo "не могу запустить файл" fi Этот же пример можно записать по-другому: [ -x /usr/games/pool ] && /usr/games/pool || echo "не могу запустить файл" Циклы реализуются с помощью конструкций for, while. Цикл for записывается так: for <переменная> in <список> do <команды> done Пример 1: for i in 1 2 3 do echo $i done Пример 2: for file in /etc/p* do echo $file done Этот цикл эквивалентен команде ls /etc/p*. Цикл while имеет вид: while <условие> do <команды> done Команды в теле цикла выполняются до тех пор, пока остается истинным <условие>. Пример: i=1 while [ $i -lt 5 ] do echo $i i = $(($i+1)) # можно было бы написать i=`expr $i + 1` done Другим вариантом цикла while является until. until <условие> do <команды> done В этом случае команды в теле цикла выполняются до тех пор, пока <условие> остается ЛОЖНЫМ. i=1 until ! [ $i -lt 5 ] do echo $i i=`expr $i + 1` done Заметим, что по команде break можно выйти из тела цикла. Это справедливо и для цикла for и для while (until). Пример: i=1 while [ $i -gt 0 ] do echo $i i=`expr $i + 1` if [ $i -eq 10 ] ; then break fi done Передача аргументов. Команда shift. При запуске на выполнение, сценарию можно передать аргументы в командной строке. Например: # /usr/games/pool file1.txt user1M Для того, чтобы можно было работать с переданными аргументами, существует девять переменных - $1, $2, : , $9. Они позиционно соответствуют переданным аргументам. Т.е. в нашем примере $1 содержит строку "file.txt", а $2 содержит строку "user1". Кроме того, в переменной $# содержится количество переданных аргументов. В нашем случае - 2. Но что делать, если нужно передать, скажет, 15 аргументов ? Как получить доступ к аргументу с номером больше 9 ? Для этой цели существует команда shift, которая просто осуществляет сдвиг аргументов на одну позицию <влево>. Т.е. $1 получает значение $2, $2 - $3 и т.д. При этом значение, которое было в $1 до сдвига - теряется. При этом сдвиге так же уменьшается на 1 значение $#. Рассмотрим это на примере. Создайте такой файл #!/usr/local/bin/bash i=1 while [ $# -eq 0 ] do echo "Аргумент $i - $1" shift i=`expr $i + 1` done Назовите его, например, my_shift. Запустите его так: # my_shift p1 p2 p3 p4 На экране вы увидете: Аргумент 1 - p1 Аргумент 2 - p2 Аргумент 3 - p3 Аргумент 4 - p Упражнения
Ответ (пример скрипта): #!/usr/local/bin/bash if [ $# -gt 1 ] ; then file=$1 i=$# shift while [ $# -eq 0 ] do cat $1 >> $file shift done echo "Всего к файлу $file добавлено `expr $i - 1` файлов" else echo "Недостаточно аргументов" fi [Назад][Содержание][Вперед] |
|
| ||||||||||||||||
|