Язык программирования shell имеет
несколько конструкций, которые
придадут гибкость вашим
программам:
- комметнарии позволят
описывать функции программы;
- "here document" позволяет вам
включать в shell программы
строки, которые будут
перенаправляться как ввод в
некоторые команды shell
программы;
- команда exit позволяет завершать
программу в нужной точке и
использовать коды возврата;
- конструкции цикла for, while
позволяют повторять группу
команд в цикле;
- условные команды if и case
выполняют группу команд, если
выполнилось некоторое условие;
- команда break позволяет
выполнить безусловный выход из
цикла.
9.3.1. Комментарии
Чтобы в программе разместить
комментарии, воспользуйтесь знаком
#. Если знак # стоит после команды, то
сама команда выполняется, а
комментарий игнорируется. Формат
строки комментария:
#comment<CR>
9.3.2. "Here document"
"Here document" позволяет
размещать в shell программе строки,
которые перенаправляются в
качестве ввода команды в этой
программе. Это один из способов
обеспечения ввода для команды в shell
программе без использования
отдельного файла. Запись состоит из
символа перенаправления << и
разделителя, который указывает
начало и конец строк ввода. В
качестве разделителя может
использоваться один символ или
строка символов. Чаще всего это
знак !.
Формат команды следующий:
command<<delimiter<CR>
...input lines...<CR>
delimiter<CR>
9.3.3. Использование ed в shell
программе
"Here document" предлагает способ
использования ed в shell программе.
Предположим вы хотите создать shell
программу, которая будет вызывать
редактор ed, проводить глобальные
изменения в файле, записывать
изменения в файл и затем завершать
работу с ed. На следующем экране
приведено содержание программы
ch.text, которая выполняет эти задачи:
$ cat ch.text<CR>
echo Type in the filename
read file1
echo Type in the exact text to be changed.
read old_text
echo Type in the exact new text to replace the above.
read new_text
ed - $file1 <<!
g/$old_text/s//$new_text/g
w
q
!
$
Обратите внимание на знак - (минус)
в команде ed. Эта опция
предотвращает распечатку счетчика
символов на экране. Обратите также
внимание на формат команды ed для
глобальной замены:
g/$old_text/s//$new_text/g
Программа использует 3
переменные: file1, old_text, new_text. При
запуске эта программа использует
команду read для получения значений
этих переменных. Эти переменные
содержат следующую информацию:
file - имя файла, который будет
редактироваться;
old_text - текст, который будет изменен;
new_text - новый текст.
Переменные вводятся в программу,
here document перенаправляет команду
глобальной замены, команду записи и
команду завершения команде ed.
Запустите программу ch.text. Получите
следующий экран:
$ ch.text<CR>
Type in the filename
memo<CR>
Type in the exact text to be changed.
Dear John:<CR>
Type in the exact new text to replace the above.
To what it may concern:<CR>
$ cat memo<CR>
To what it may concern:<CR>
$
9.3.4. Коды завершения
Большинство команд shell возвращает
коды, которые указывают, успешно ли
завершилась команда. Если
возвращаемое значение 0(ноль), то
команда выполнилась успешно. Коды
возврата не печатаются
автоматически, но их можно получить
как значение специального
параметра shell $?.
9.3.4.1. Проверка кодов завершения
После выполнения в интерактивном
режиме команды, вы можете увидеть
код завершения при вводе:
echo $?
Рассмотрим следующий пример:
$ cat hi
This is file hi.
$ echo $?
0
$ cat hello
cat: cannot open hello
$ echo $?
2
$
В первом случае файл hi существует
в вашем справочнике и вы имеете
разрешение на чтение. С помощью
команды cat вы можете распечатать
содержимое файла. Результат
команды cat: код возврата 0, который
вы получите, задав параметр $?. Во
втором случае файл либо не
существует, либо вы не имеете право
на чтение. Команда cat печатает
диагностическое сообщение и
возвращает код 2.
shell программа нормально
завершается, когда выполнится
последняя команда в файле. Однако
вы можете использовать команду exit
для завершения программы. Более
важно то, что вы можете
использовать команду exit для
получения кодов возврата shell
программы.
9.3.5. Циклы
Операторы цикла for и while позволяют
выполнить команду или
последовательность команд
несколько раз.
9.3.5.1. Оператор for
Оператор for выполняет
последовательность команд для
каждого элемента списка. Он имеет
формат:
for variable<CR>
in a_list_of_values<CR>
do<CR>
command_1<CR>
command_2<CR>
.
.
.
last command<CR>
done<CR>
Для каждой итерации цикла
следующий элемент списка
присваивается переменной, данной в
операторе for. Ссылка на эту
переменную может быть сделана в
любом месте в командах внутри
оператора do. При конструировании
каждой секции команд вам
необходимо убедиться, что каждому do
соответствует done в конце цикла.
Переменная может иметь любое имя.
Например, если ваша переменная
названа var, то ссылка в списке
команд на $var сделает значение
доступным. Если оператор in опущен,
то значением для var будет набор
аргументов, заданный в команде и
доступный в специальном параметре
$*. Список команд между ключевым
словом do и done будет выполнен для
каждого значения.
Когда команды будут выполнены для
последнего элемента списка,
программа будет выполнять строку
ниже done.
9.3.5.2. Оператор while
Оператор цикла while использует 2
группы команд. Он будет выполнять
последовательность команд во
второй группе (список do ... done) до тех
пор пока последняя команда в первой
группе (список while) возвращает
состояние "истина",
означающее, что выражение после do
может быть выполнено.
Общий формат оператора цикла
while:
while<CR>
command_1<CR>
.
.
.
last command<CR>
do<CR>
command_1<CR>
.
.
.
last command<CR>
done<CR>
Например, программа enter.name
использует цикл while для ввода
списка имен в файл. Программа
состоит из следующих командных
строк:
$ cat enter.name<CR>
while
read x
do
echo $x>>xfile
done
$
Внеся некоторые добавления,
получим следующую программу:
$ cat enter.name<CR>
echo Please type in each person's name and than a <CR>
echo Please end the list of names with a <^d>
while read x
do
echo $x>>xfile
done
echo xfile contains the following names:
cat xfile
$
Обратите внимание, что после
завершения цикла программа
выполняет команды ниже done.
В первых двух командах echo
используются специальные символы,
так что вы должны воспользоваться
кавычками для отмены специального
значения. На следующем экране
приведены результаты выполнения
программы enter.name:
$ enter.name<CR>
Please type in each person's name and than a <CR>
Please end the list of names with a <^d>
Mary Lou<CR>
Janice<CR>
<^d>
xfile contains the following names:
Mary Lou
Janice
$
После того, как цикл завершится,
программа распечатает все имена,
содержащиеся в xfile.
9.3.6. Использование /dev/null
Файловая система имеет файл /dev/null,
где вы можете хранить
нежелательный вывод. Например, если
просто ввести команду who, то система
ответит, кто работает в системе.
Если вы перенаправите вывод этой
команды в /dev/null:
who > /dev/null
то не получите ответа.
9.3.7. Условные операторы
Оператор if ... then
Команда if говорит shell программе,
что нужно выполнить
последовательность команд после
then, если последняя команда в списке
команд конструкции if выполнилась
успешно. Конструкции if
заканчиваются ключевым словом fi.
Общий формат конструкции if:
if<CR>
command_1<CR>
.
.
.
last command<CR>
then<CR>
command_1<CR>
.
.
.
last command<CR>
fi<CR>
Например, shell программа search
демонстрирует применение
конструкции if ... then. Программа search
использует команду grep для поиска
слова в файле. Если grep выполнилась
успешно, то программа отображает
найденное слово. Экран будет
выглядеть следующим образом:
$ cat search<CR>
echo Type in the word and the file name.
read word file
if grep $word $file
then echo $word is in $file
fi
$
Эта программа отображает вывод
команды grep. Если вы хотите
сохранить ответ системы на команду
grep в вашей программе, то
воспользуйтесь файлом /dev/null,
изменив командную строку if на
следующую:
if grep $word $file > /dev/null<CR>
Теперь выполните команду search. Она
ответит только сообщением,
указанным после команды echo.
Конструкция if ... then ... else может
исполнять альтернативный набор
команд, стоящий после else, в случае,
если последовательность if является
ложью. Формат этой конструкции
следующий:
if<CR>
command_1<CR>
.
.
.
last command<CR>
.linthen<CR>
command_1<CR>
.
.
.
last command<CR>
else<CR>
command_1<CR>
.
.
.
last command<CR>
fi<CR>
С помощью этой конструкции вы
можете усовершенствовать
программу search, так что она будет
сообщать вам и найденное слово и то,
что слово не найдено. В этом случае
программа search будет выглядеть
следующим образом:
$ cat search<CR>
echo Type in the word and the file name.
read word file
if
grep $word $file > /dev/null
then
echo $word is in $file
else
echo $word is NOT in $file
fi
$
Команда test
Команда test используется для
организации цикла. Она проверяет на
истинность определенные условия и
полезна для организации условных
конструкций. Если условие истинно,
то цикл будет продолжен. Если
условие ложно, то цикл завершится и
будет выполняться следующая
команда. Некоторые примеры
использования команды test:
- test -r file<CR>
- истина, если файл существует и
доступен для чтения;
- test -w file<CR>
- истина, если файл существует и
доступен для записи;
- test -x file<CR>
- истина, если файл существует и
является выполняемым;
- test -s file<CR>
- истина, если файл существует и
имеет как минимум один символ;
- test var1 -eq var2<CR>
- истина, если var1 равно var2;
- test var1 -ne var2<CR>
- истина, если var1 не равно var2.
Пример. Создадим shell программу,
которая перемещает все исполняемые
файлы из текущего справочника в ваш
справочник bin. Для этого
воспользуемся командой test -x для
выбора исполняемых файлов.
Программа mv.file будет выглядеть
следующим образом:
$ cat mv.file<CR>
echo type in the directory path
read path
for file
do
if test -x $file
then
mv $file $path/$file
fi
done
$
Конструкция case ... esac позволяет
выбрать вам один из несколько
шаблонов и затем выполнить список
команд для этого шаблона.
Выражение-шаблон должно начинаться
с ключевого слова in, а правая
круглая скобка должна быть
помещена после последнего символа
каждого шаблона.
Последовательность команд для
каждого шаблона заканчивается
двумя знаками ;;. Конструкция case
должна быть закончена ключевым
словом esac.
Общий формат конструкции case:
case word<CR>
in<CR>
pattern1)<CR>
command line 1<CR>
.
.
.
last command line<CR>
;;<CR>
pattern2)<CR>
command line 1<CR>
.
.
last command line<CR>
;;<CR>
pattern3)<CR>
command line 1<CR>
.
.
last command line<CR>
;;<CR>
*)<CR>
command line 1<CR>
.
.
last command line<CR>
;;<CR>
esac<CR>
Конструкция case пытается найти word
с шаблоном pattern в первой секции
шаблонов. Если поиск удачен, то
программа выполняет командные
строки после первого шаблона до
соответствующих знаков ;;.
Если первый шаблон не найден, то
осуществляется переход ко второму
шаблону. Если любой шаблон найден,
то программа не рассматривает
остальные шаблоны, а переходит к
команде, следующей за esac. Знак *
используется как шаблон для поиска
любого word и таким образом дает вам
набор команд, который будет
выполнен, если никакой другой
шаблон не будет найден. Поэтому
шаблон звездочка (*) размещается как
последний шаблон в конструкции case,
чтобы другие шаблоны были
проверены первыми. Это поможет вам
обнаружить некорректный и
неожиданный ввод.
В шаблонах могут использоваться
метасимволы *, ?, []. Это обеспечивает
гибкость программ.
Рассмотрим пример. Программа set.term
устанавливает переменную TERM в
соответствии с типом терминала,
который вы используете.
Применяется следующая командная
строка:
TERM=terminal_name<CR>
Шаблон * стоит последним в списке
шаблонов. Он выдает
предупреждающее сообщение, что для
указанного типа терминала нет
соответствующего шаблона и
позволяет вам завершить
конструкцию case.
Пример.
$ cat set.term<CR>
echo If you have a TTY 4420 type in 4420
echo If you have a TTY 5410 type in 5410
echo If you have a TTY 5420 type in 5420
read term
case term
in
4420)
TERM-T4
;;
5410)
TERM-T5
;;
5420)
TERM-T7
;;
*)
echo not a correcr terminal type
;;
esac
export TERM
echo end of programm
$
9.3.8. Безусловная передача
управления
Команда break безусловно
останавливает выполнение любого
цикла, в котором он встречается и
передает управление команде,
следующей после ключевых слов done, fi
или esac.
В предыдущем примере программы
set.term вы можете использовать
команду break, вместо echo, чтобы выйти
из программы, как приведено в
следующем примере:
Пример.
$ cat set.term<CR>
echo If you have a TTY 4420 type in 4420
echo If you have a TTY 5410 type in 5410
echo If you have a TTY 5420 type in 5420
read term
case term
in
4420)
TERM-T4
;;
5410)
TERM-T5
;;
5420)
TERM-T7
;;
*)
break
;;
esac
export TERM
echo end of programm
$
Команда continue приведет к тому, что
программа немедленно перейдет к
следующей итерации цикла while или for
без выполнения остальных команд в
цикле.
|