- •План лабораторних робіт
- •Лабораторна робота № 1
- •Лабораторна робота № 2
- •Лабораторна робота №3
- •Norton commander: панелі і функціональні клавіші Утримання панелей Norton Commander
- •Головне меню
- •Лабораторна робота № 4
- •Вивести на екран дерево каталогів на диску і відшукати там свої каталоги.
- •Можливості Norton Commander
- •Лабораторна робота № 5
- •Лабораторна робота № 6
- •Лабораторна робота № 7
- •Лабораторна робота № 8
- •Лабораторна робота № 9
- •Лабораторна робота № 10
Лабораторна робота № 10
Тема: Програмування на мові В- Shell. Керуючі структури Shell.
Мета: Вивчити основні змінні OS UNIX, навчитися розробляти складні сценарії та команди редагування OS UNIX за допомогою керуючих структур B Shell.
Завдання:
1. Змініть первинну підказку таким чином щоб вона була схожа до підказки OS DOS.
2. Змініть вторинну підказку на будь-яке повідомлення.
3. Вивчення змінної PATH
4. Створіть shell-програму, яка виконує дії аналогічні до дії команди TREE MS-DOS.
5. В своєму домашньому каталозі та його підкаталогах знайти всі файли з розширенням .atc і склеїти їх в один файл, який необхідно розмістити в новому каталозі. Відсортувати і вивести вміст файлу на екран.
6. Перебрати в своєму домашньому каталозі, його підкаталогах всі файли і знайти той, який містить вказане слово, введене з клавіатури.
7. Відкрити текстовий файл, рахувати з нього 20 символів і записати їх в новий файл. Вивести на екран вміст старого і нового файлу.
8. Ввести з клавіатури ім'я файлу.
Якщо він існує, то на екран видається меню:
1 - Проглядання файлу;
2 - Редагувати файл (редактором ed);
3 - Сортувати файл;
4 - Пошук у файлі;
5 - Видалити файл;
6 - Вихід з програми.
Якщо заданий файл не існує, то програма запрошує дозвіл на створення файлу з вказаним ім'ям. Якщо «так», то створюється порожній файл і на екран видається меню:
1 - Редагувати файл (редактором ed);
2 - Проглядання файлу;
3 - Вихід з програми.
Меню повинне бути організовано в циклі.
9. Порівнюються два каталоги.
Знайти файли з однаковими іменами і порівняти їх вміст. Якщо вони ідентичні один одному, то вивести місце їх розташування і запит на видалення одного з них. Якщо «так», то програма видаляє файл з того місця, яке вказав користувач. Якщо вони різні по вмісту, то вивести повідомлення про це і вказати місце їх розташування.
Обладнання та матеріали: ПК, ОС UNIX, методичні вказівки до лабораторних робіт.
Хід роботи :
Ознайомитись з теоретичними відомостями.
На комп’ютері з операційною системою UNIX, запустити командний інтерпретатор В- Shell.
Виконти дії з первинними та вторинними підказками, відповідно до завдання.
Створіть shell-програму, яка виконує дії аналогічні до дії команди TREE MS-DOS.
Виконати дії з каталогами та підкаталогами, відповідно до завдання.
Виконати пошук файлів, відповідно до завдання.
Виконати дії з каталогами, відповідно до завдання.
Організувати меню, відповідно до завдання.
Виконати порівняння каталогів, відповідно до завдання.
Оформити та захистити звіт лабораторної роботи.
Теоретичні відомості
Shell і команди
Shell - це просто програма, яка сприймає введене користувачем, (тобто команди, які ви надрукуєте) і транслює це в команди системі. Це можна порівняти з програмою COMMAND.COM під MS-DOS, яка робить щось схоже. Shell - це лише один з інтерфейсів UNIX.
Як тільки ви ввійшли, система запускає shell, і ви можете вводити для нього команди. Ось короткий приклад. Якраз Larry увійшов до системи, і система знов видала підказку:
mousehouse login: larry
Password: larry's password
Welcome to Mousehouse!
/home/larry#
/home/larry#" це підказка shell, що показує, що він готовий приймати команди. /home/larry# make love
make: *** No way to make target 'love'. Stop.
"make" - це ім'я існуючої в системі програми і shell намагався виконати цю команду.
Перше слово командного рядка "make" це ім'я команди, яку передбачається виконати. Все інше в командному рядку сприймається як аргументи команди.
Приклади:
/home/larry# cp foo bar
Тут ім'я команди "cp", а аргументи "foo" і "bar".
Коли ви вводите команду, shell робить декілька речей. По-перше, дивиться на те, що може (повинно) бути ім'ям команди і є це внутрішньої для shell командою. Shell також перевіряє, чи не є команда синонімом іншої або потрібен підстановка імені. Якщо цього не треба робити, shell шукає відповідну цьому імені програму на диску. Якщо shell знаходить таку програму, він її виконує, передаючи їй аргументи з командного рядка.
В нашому прикладі shell шукає програму на ім'я make і намагається виконати її з аргументом love. make - це програма, яка часто використовується при компіляції великих програм, вона бере як аргумент ім'я "цільового файлу" компіляції. У разі "make love" ми наказали команді make відкомпілювати love. Оскільки make не зміг знайти файлу з таким ім'ям, він повідомив (дещо забавним чином) про неможливість виконати команду і повернувся в підказку.
Shell - інтерпретатор командної мови
Метасимволи
Сім віл
|
Функція
|
* ? [ ]
|
Ці метасимволи дозволяють вказувати скорочені імена файлів при пошуку за шаблоном
|
&
|
Означає, що команда виконуватиметься у фоновому режимі
|
;
|
Крапка з комою розділяє команди в командному рядку
|
\
|
Відміняє спеціальне значення символів, таких як * ?, [ ] & ; < >
|
‘.’
|
Одиночні лапки відміняють значення пропуску як роздільника і спеціальне значення всіх символів
|
“.”
|
Подвійні лапки відміняють значення пропуску як роздільника і спеціальне значення всіх символів, за виключенням $ і \
|
>
|
Перенаправляє висновок команди у файл
|
<
|
Перенаправляє введення для команди з файлу
|
»
|
Перенаправляє висновок команди, який повинен бути доданий в кінець існуючого файлу
|
|
|
Створює канал, направляюче виведення однієї команди у введення іншої команди
|
ММММ.М
|
Використовується в парі; дозволяє використовувати висновок як аргументи в командному рядку
|
$
|
Використовується з позиційними параметрами і визначеними користувачем змінними; також використовується за умовчанням як підказка, shell
|
Метасимволи використовуються для пошуку імен файлів, за допомогою їх спрощується задача вказівки файлів або груп файлів як аргументів команди.
Пошук всіх символів (метасимвол *)
Метасимвол * здійснює пошук будь-якого рядка символів, включаючи нульовий (порожнію) рядок. Ви можете використовувати * для позначення повного або часткового імені файлу. Просто символ * шукає всі імена файлів і довідників в поточному довіднику, за винятком тих, які починаються з крапки. Щоб подивитися метасимвол * у дії, введіть його як аргумент в команді echo:
echo *<CR>
У відповідь система роздрукує перелік всіх імен файлів у вашому поточному довіднику.
Символ * може представляти символи в будь-якій частині імені файлу.
Якщо у вашому довіднику знаходяться файли FATE, FE, FADED_LINE, FIG3.4E, FINE_LINE, FAST_LINE, то для відображення всіх цих файлів на екрані введіть команду:
Is F*E<CR>
Ви можете, наприклад, за допомогою метасимвола "' знайти всі файли з іменами memo в системному довіднику: ls */memo
Пошук по одному символу (метасимвол ?)
Метасимвол ? здійснює пошук будь-якого одного символу в імені файлу за винятком лідируючої крапки. Припустимо, ви маєте книгу, в якій 12 глав і хочете отримати список глав до 9-го розділу. Якщо ваш довідник містить наступні файли:
Chapter 1
Chapter2
Chapter5
Chapter9
Chapter 11
то введіть команду ls з метасимволом ? для отримання всіх глав, які починаються з рядка "Chapter" і закінчуються одним символом:
$ Is Chapter?<CR>
Chapter 1
Chapter2
Chapters
Chapter9
$
Хоча метасимвол здійснює пошук одного символу, ви можете використовувати його для пошуку більше одного символу в імені файлу. Наприклад, ви отримаєте перелік всієї решти розділів в поточному довіднику, якщо введете наступну команду:
ls Chapter??<CR>
І, звичайно, щоб отримати список всіх глав в поточному довіднику, використовуйте метасимвол *:
ls Chapter*<CR>
Пошук одного набору (метасимвол [ ])
Якщо ви хочете, щоб shell знайшов будь-який символ з перерахованих вами символів, то укладете ці символи в квадратні дужки. Припустимо, ваш довідник містить наступні файли: cat, fat, mat, rat. Якщо ви скористаєтеся як частина імені файлу шаблоном [erf], то shell шукатиме імена файлів, в які входять або буква "с", або буква "r", або буква "f" у вказаній позиції. Приклад:
$ Is [crf]at<CR>
cat
fat
rat
$
Символи, які можуть бути згрупований в дужки, називаються класом символів.
Дужки можуть також використовуватися для позначення діапазону символів, цифр або букв. Припустимо у вашому довіднику містяться наступні файли: chapteri, chapter2, chapters, chapter4, chapter5, chapter6. Якщо ви вкажете:
chapter[1-5]
то shell знайде файли з chapteri по chapter5.
Клас символів можна також вказати за допомогою діапазону букв. Якщо ви вкажете [A-Z], то shell шукатиме тільки великі букви, якщо [а-z] - то малі букви.
Створення простих програм shell
Почнемо опис створення простих програм shell, які виконують задачі:
друк поточного довідника;
список вмісту цього довідника;
відображення наступних повідомлень на вашому терміналі: "This is end shell program."
За допомогою редактора створіть файл dl і введіть в нього рядки:
pwd<CR>
ls<CR>
echo This is end shell program.<CR>
Тепер ви маєте програму shell. Ви можете за допомогою cat відобразити вміст файлу:
$ cat dl<CR> pwd
ls
echo This is end shell program.
$
Виконання програм shell
Виконати shell програму ви можете за допомогою команди sh. Введіть:
sh dl<CR>
Коли команда dl виконується за допомогою sh, то спочатку друкується ім'я шляху поточного довідника, потім список файлів в поточному довіднику і в кінці коментар: "This is end shell program."
За допомогою команди chmod ви можете зробити файл виконуваним:
$ chmod u+x dl<CR>
$ls-KCR>
total 2
-xw—— 1 login login 3661 Nov 2 10:28 mbox
-xwx-— 1 login login 48 Nov 15 10:50 dl
$
Зверніть увагу, що chmod включає дозвіл на виконання (+х) для користувача (и). Тепер dl є виконуваною програмою. Спробуйте виконати її. Введіть:
dl<CR>
Створення довідника bin для виконуваних файлів
Щоб зробити shell програми доступними зі всіх ваших довідників, ви можете створити довідник bin в своєму реєстраційному довіднику і переписати shell програми в цей довідник.
За допомогою змінної PATH ви можете включити ваш довідник" bin:
PATH = $PATH:$HOME/bin
Як у всякій мові програмування в тексті на мові shell можуть бути коментарі. Для цього використовується символ "#". Все, що знаходиться в рядку (в командному файлі) ліворуч цього символу, сприймається інтерпретатором як коментар. Наприклад
# Це коментар.
## І це.
### І це теж.
Як у всякій процедурній мові програмування, в мові shell є оператори. Ряд операторів дозволяє управляти послідовністю виконання команд. В таких операторах часто необхідна перевірка умови, яка і визначає напрям продовження обчислень.
Умовний оператор if
В загальному випадку оператор "if має структуру
if умова
then список
[elif умова
then список]
[else список]
fi
Тут "elif скорочений варіант від "else if може бути використаний разом з повним, тобто допускається вкладення довільного числа операторів "if (як і інших операторів). Зрозуміло "список" в кожному випадку повинен бути осмислений і допустимий в даному контексті.
Конструкції
[elif умова
then список]
і
[else список]
не є обов'язковими
Сама усічена структура цього оператора
if умова
then список
fi
якщо виконана умова (як правило це грудка отриманий код завершення "О", то виконується "список", інакше він пропускається.
Зверніть увагу, що структура обов'язково завершується службовим словом "fi". Число "fi", природно, завжди повинне відповідати числу "if.
Приклади.
Хай написаний розрахунок "if-1"
if[$l-gt$2]
then pwd
else echo $0 : Hello!
Fi
Тоді виклик розрахунку
if-1 12 11
дасть
/home/sae/STUDY/SHELL
а
if-1 12 13
дасть
if-1: Hello!
Ще приклад на вкладеність
###
# if-3: Оцінка досягнень
echo -n " А яку оцінку отримав на іспиті?: " readz
if[$z=5]
then echo Молодець ! elif[$z=4]
then echo Все одно молодець ! elif[$z=3] then echo Все одно ! elif[$z=2] then echo Все ! else echo ! fi
Можна звернути увагу на те, що бажано використовувати зсуви при записі програм, щоб краще виділити вкладеність структур.
Оператор вибору "case" має структуру:
Конструкція case ... esac дозволяє вибрати вам один з декілька шаблонів і потім виконати список команд для цього шаблона. Вираз-шаблон повинен починатися з ключового слова in, а права кругла дужка повинна бути поміщений після останнього символу кожного шаблона. Послідовність команд для кожного шаблона закінчується двома знаками ;;. Конструкція case повинна бути закінчений ключовим словом esac.
case рядок in
шаблон) список команд;;
шаблон) список команд;;
.
esac
Приклад.
###
# case-1: Структура "case".
# Вже що розглядався в зв'язку з
# структурою "if приклад простіше і
# наглядніше можна реалізувати з
# допомогою структури "case".
echo -n " А яку оцінку отримав на іспиті?: "
read z
case $z in
5) echo Молодець ! ;;
4) echo Все одно молодець ! ;;
3) echo Все одно ! ;;
2) echo Все ! ;;
#) echo ! ;; ^ esac
Незвикло виглядають в кінці рядків вибору ";;", але написати тут ";" було б помилкою. Для кожної альтернативи може бути виконано декілька команд. Якщо ці команди будуть записані в один рядок, то символ ";" використовуватиметься як роздільник команд.
Звичайно останній рядок вибору має шаблон "*", що в структурі "case" означає "будь-яке значення". Цей рядок вибирається, якщо не відбувся збіг значення змінної (тут $z) ні з одним з раніше записаних шаблонів, обмежених дужкою ")". Значення є видимими в порядку запису.
###
# case-2: Довідник.
# Для різних фірм на ім'я видається
# назва холдингу, в який вона входить
case $1 in
ONE|TWO|THREE) echo Холдинг: ZERO ;;
MMM|WWW) echo Холдинг: Not-Net;;
Hi|Hello[Howdoing) echo Холдинг: Привіт! ;;
*) echo Немає такої фірми ;;
esac
При виклику "case-2 Hello" на екран буде виведений:
Холдинг: Привіт!
А при виклику "case-2 HELLO" на екран буде виведений:
Немає такої фірми
Коли скоро слово "case" переводиться як "вибір", то це як би натяк на те, що можна цю структуру використовувати для реалізації найпростіших меню.
###
# case-3: Реалізація меню за допомогою команди "case echo" "Назвіть файл, а потім (через пропуск) наберіть цифру, відповідну необхідній обробці:
1 - відсортувати
2 - видати на екран
3 - визначити число рядків "
read х у # х - ім'я файлу, у - що зробити
case $y in
1)sort<$x„
2)cat<$x;;
3) we -1 < $x ;;
*) echo "
Ми не знаємо
такої команди ! " ;;
esac
Зрозуміло, бажання можуть бути складніші і на місці окремих команд можуть бути послідовності команд або виклики складніших розрахунків.
Напишемо команду "case-4", яка додає інформацію до файлу, вказаного першим параметром (якщо параметр один), із стандартного входу, або (якщо 2 параметри) з файлу, вказаного як перший параметр:
###
# case-4: Додавання у файл.
# Використовування стандартної змінної.
# "$#" - число параметрів при введенні розрахунку
# "»" - перенаправлення з додаванням у файл
case $# in
1)cat»$l ;;
2)cat»$2<$l ;;
*) echo "Формат: case-4 [звідки] куди";;
esac
"$1" (при "$#=1") - це ім'я файлу, в який відбувається додавання із стандартного входу.
"$1" і "$2" (при $#-2) - це імена файлів, з якого ("$!") і в який ("$2") додавати.
У всіх інших випадках (*) видається повідомлення про те, яким повинен бути правильний формат команди.
Оператор циклу з переліком ("for")
Оператор for виконує послідовність команд для кожного елемента списку. Для кожної ітерації циклу наступний елемент списку привласнюється змінній, даній в операторі for. Посилання на цю змінну може бути зроблено в будь-якому місці в командах усередині оператора do. При конструюванні кожної секції команд вам необхідно переконатися, що кожному do відповідає done в кінці циклу.
Оператор циклу "for" має структуру:
for ім'я [in список значень]
do
список команд
done
де "for" - службове слово визначаюче тип циклу, "do і "done" -службові слова", виділяючі тіло циклу. Не забувайте про "done"! Фрагмент "in список значень" може бути відсутній.
Часто використовується форма "for i in *", що означає "для всіх файлів поточного каталога".
Хай "proc-sort" у свою чергу представляється командним файлом
cat $ 1 | sort | tee /dev/lp > ${ 1 }_sorted
тобто послідовно сортуються вказані файли, результати сортування виводяться на друк ("/dev/lp") і прямують у файли fl_sorted f2_sorted і f3_sorted
Можна зробити більш універсальною команду "Isort", якщо не фіксувати перелік файлів в команді, а передавати довільне їх число параметрами.
Тоді головна програма буде наступною:
for i
do
proc-sort $i '
done
Тут відсутність після "i" службового слова "in" з переліком імен говорить про те, що список поступає через параметри команди. Результат попереднього прикладу можна отримати, набравши
Isort fl Ј2 f3
Ускладнимо задачу визначення холдингу фірми, що раніше розглядалася. Тепер можна при виклику указувати довільну кількість фірм. За відсутності в структурі оператора "for фрагмента" "in список значень", значення беруться з параметрів зухвалої команди.
###
# holding: Довідник.
# Для різних фірм на ім'я видається
# назва холдингу, в який вона входить
fori
do
case $i in
ONE|TWO|THREE) echo Холдинг: ZERO ;;
MMM|WWW) echo Холдинг: Not-Net;;
Hi|Hello|Howdoing) echo Холдинг: Привіт! ;;
*) echo Немає такої фірми ;;
esac
done
При виклику "holding Hello HELLO ONE" на екрані буде:
Холдинг: Привіт!
Немає такої фірми
Холдинг: Not-Net
Наступний розрахунок ілюструє корисний, хоча і з часткою трюкача, спосіб повторення одних і тих же дій кілька разів. Змінна "i" приймає тут п'ять значень: 1, 2, 3, 4, 5, але усередині циклу ця змінна відсутня і тому її значення ніякої ролі не грає і ні чого не міняє. З таким же успіхом змінна "i" могла приймати значення, скажемо ф про до у з, а в результаті точно також би було п'ять разів повторено одне і те ж обчислення вмісту циклу без змін.
###
# print-5: Організації п'ятикратного виконання команди
for i in 1 2 3 4 5
do
cat file-22 > /dev/lp
done
Розрахунок "print-n" ілюструє ще одну корисну можливість у використовуванні циклу "for". Тут, після "for i...", відсутні "in..." і перелік імен, тобто переліком імен для "i" стає перелік параметрів," а отже кількість друкованих екземплярів можна міняти.
###
# print-n: Завдання числа копій
# через параметри
for i
do
cat file-22 > /dev/lp
done
Значення не зміниться, якщо перший рядок розрахунку записати як
for i in $*
оскільки значення "$*" - є список значень параметрів.
Відзначимо відмінність в спеціальних змінних "$*" і "$@", що представляють перелік параметрів. Перший представляє параметри, як рядок, а другий, як сукупність слів.
Хай командний файл "сmр" має вигляд:
for i in "$*"
do
echo $i
done
echo
for i in "$@"
do
echo $i
done
При виклику
cmp aa bb cc
на екран буде виведений
аа bb cc
аа
bb
cc
Оператор циклу з істинною умовою ("while")
Структура "while", також забезпечуюча виконання розрахунків, переважно тоді, коли невідомий наперед точний список значень параметрів або цей список повинен бути отриманий в результаті обчислень в циклі.
Оператор циклу "while" має структуру:
while умова
do
список команд
done
де "while" - службове слово визначаюче тип циклу з істинною умовою. Список команд в тілі циклу (між "do" і "done") повторюється до тих пір, поки зберігається істинність умови (тобто код завершення останньої команди в тілі циклу рівний "О") або цикл не буде перерваний зсередини спеціальними командами ("break", "continue" або "exit"). При першому вході в цикл умова повинна виконуватися.
###
# print-50: Структура "while"
# Розрахунок дозволяє надрукувати 50
# екземплярів файлу "file-22"
n=0
while [ $n -It 50 ] # поки п < 50
do
n='expr $n+ Г
cat file-22 > /dev/lp
done
Звернемо увагу на те, що змінній "п" спочатку привласнюється значення 0, а не порожній рядок, оскільки команда "ехрr" працює з shell-змінними як з цілими числами, а не як з рядками.
n='ехрr $n+ 1’
тобто при кожному виконанні значення "n" збільшується на 1.
Як і взагалі в житті, можна реалізувати те ж саме і складніше. Розрахунок "pr-br" приведений для ілюстрації нескінченного циклу і використовування команди "break", яка забезпечує припинення циклу.
###,
# pr-br: Структура "while" з "break"
# Розрахунок дозволяє надрукувати 50
# екземплярів файлу "file-22 n=0"
while true
do
if[$n-lt50] #якщо n<50
then n=’expr $n+1'
else break
fi
cat file-22 > /dev/lp
done
Команда "break [n]" дозволяє виходити з циклу. Якщо "п" відсутній, то це еквівалентно "break I", "n" указує число вкладених циклів, з яких треба вийти, наприклад, "break 3" - вихід з трьох вкладених циклів.
На відміну від команди "break команда" "continue [n]" лише припиняє виконання поточного циклу і повертає на ПОЧАТОК циклу. Вона також може бути з параметром. Наприклад, "continue 2" означає вихід на початок другого (якщо вважати з глибини) вкладеного циклу.
Команда "exit [n]" дозволяє вийти взагалі з процедури з кодом повернення "О" або "n" (якщо параметр "n" вказаний). Ця команда може використовуватися не тільки в циклах. Навіть в лінійній послідовності команд вона може бути корисний при відладці, щоб припинить виконання (поточного) розрахунку в заданій крапці.
Оператор циклу з помилковою умовою ("until")
Оператор циклу "until" має структуру:
until умова
do
список команд
done
де "until" - службове слово визначаюче тип циклу з помилковою умовою. Список команд в тілі циклу (між "do" і "done") повторюється до тих пір, поки зберігається помилковість умови або цикл не буде перерваний зсередини спеціальними командами ("break", "continue" або "exit"). При першому вході в цикл умова не повинна виконуватися.
Відмінність від оператора "while" полягає в тому, що умова циклу перевіряється на помилковість (на ненульовий код завершення останньої команди тіла циклу) перевіряється ПІСЛЯ кожного (у тому числі і першого!) виконання команд тіла циклу.
Програмістів, знайомих з операторами "until" в інших мовах може спочатку збивати така семантика цього оператора.
Приклади.
until false
do
readx
if[$x=5]
then echo enough ; break
else echo some more
fi
done
Тут програма з нескінченним циклом чекає введення слів (повторюючи на екрані фразу "some more"), поки не буде введений "5". Після цього видається "enough" і команда "break" припиняє виконання циклу.
Інший приклад ("Очікування півдня") ілюструє можливість використовувати в умові обчислення.
until date | grep 12:00:
do
sleep 30
done
Тут кожні 30 секунд виконується командний рядок умови. Команда "date" видає поточну дату і час. Команда "grep" одержує цю інформацію через конвейєр і намагається сумістити заданий шаблон "12:00:" з часом, видаваним командою "date". При неспівпаданні "grep" видає код повернення "I", що відповідає значенню "брехня", і цикл "виконує очікування" протягом 30 секунд, після чого повторюється виконання умови. Опівдні (можливо з декількома секундами) відбудеться порівняння, умова стане істинною, "grep" видасть на екран відповідний рядок і робота циклу закінчиться.
Контрольні питання:
Що таке Shell?
Основні мета символи Shell?
Як працюють мета символи *, ?, []?
Як відбувається створення та виконання програми Shell?
Умовний оператор?
Оператор вибору?
Оператор циклу з переліком?
Оператор циклу з істинною умовою?
Оператор циклу з помилковю умовою?
Як створити довідник для виконуваних файлів?
Література:
Паркер Тим. Linux 5.2. Энциклопедия пользователя: Пер. с англ./Тим Паркер – К.: Издательство «ДиаСофт», 1999. – 688 с., стор. 176-191.
