Програмування в оболонці UNIX

Багато користувачів сприймають оболонку як інтерактивний командний процесор, але насправді вона є мовою програмування, в якому кожен оператор запускає команду Цей історично сформувався мова багато в чому незвичайний, адже йому при ходиться забезпечувати як інтерактивність, так і програмованість Різноманітність його застосувань привело до появи величезної кількості нюансів мови, хоча для ефективної роботи не обовязково знати їх усі У цьому розділі на прикладі розробки декількох корисних програм пояснюються основи програмування в оболонці Це НЕпідручник Коли ви будете читати цю главу, під рукою завжди повинна бути сторінка sh (1) довідкового керівництва з UNIX

Особливості поведінки оболонки, як і більшості інших команд, часто легше зрозуміти дослідним шляхом Керівництва можуть бути незрозумілими, і немає нічого краще вдалого прикладу, щоб прояснити ситуацію Ось чому ця глава побудована на прикладах і являє собою путівник по використанню оболонки для програмування, а не енциклопедію її можливостей Буде розказано не тільки про те, що оболонка вміє робити, а й про те, як розробляти і писати програми для неї акцент буде зроблений на інтерактивній перевірці виникають ідей

Після того як ви напишете програму в оболонці або на якому-небудь іншій мові, може виявитися, що вона так корисна, що інші поль зователя системи також захочуть з нею попрацювати Однак користувачі програм набагато вимогливіше до них, ніж їх автори Поет му головним завданням програмування в оболонці є створення

«Стійких» програм, які могли б обробити некоректні

вхідні дані і видати корисну інформацію у випадку, якщо щось пішло не так

Переробляємо команду cal

Програми оболонки часто застосовуються для поліпшення або зміни користувача інтерфейсу програми Як приклад програми, яка може бути поліпшена, розглянемо cal (1):

$ cal

usage: cal  [month]  year                 Поки все добре

$ cal  october  1983

Bad argument                                      Вже не так добре

$ cal  10 1983

October  1983

S   M  Tu    W  Th    F    S 1

2   3   4   5   6   7   8

9 10 11 12 13 14 15

16 17 18 19 20 21 22

23 24 25 26 27 28 29

30 31

$

Прикро, що місяць повинен вказуватися в числовому вигляді До того ж, виявляється, що cal 10 виводить календар для десятого року замість того, щоб робити це для поточного жовтня, і для того, щоб підлозі чить календар на один місяць, обовязково треба вказувати рік

Зверніть увагу на важливий момент: який би інтерфейс ні надавала команда cal, можна змінити його, не змінюючи саму програму Можна помістити в особистий каталог / bin команду, яка перетворювала б зручний для вас синтаксис в такий, який потрібно справжній програмі cal Свою версію можна також назвати cal – менше доведеться запамятовувати

У першу чергу слід скласти план того, що повинна виконувати cal Будемо прагнути до того, щоб програма стала розумною Вона повинна сприймати назва місяця, а не його номер Отримавши два аргументи, вона повинна вести себе в точності так само, як стара версія, і, крім того, перетворювати назви місяців в номери Якщо заданий тільки один аргумент, програма повинна вивести календар на місяць або рік (за обстановці), якщо ж аргументи не задані, нова версія cal повинна надрукувати календар на поточний місяць – очевидно, що це саме часте застосування такої команди Отже, завдання полягає в тому, щоб зрозуміти, скільки задано аргументів, потім відобразити їх згідно з правилами стандартної cal

Для таких рішень зручно використовувати оператор case:

case  словоin

шаблон)             команди ;

шаблон)             команди ;

esac

Оператор case порівнює словоз шаблонами, рухаючись зверху вниз, і виконує команди, що відповідають першому (і тільки перший) невластивому шаблоном Шаблони записуються за загальними правилами, прийнятим в оболонці для імен файлів з невеликими доповненнями Кожна дія завершується подвійний крапкою з комою;. (Остання пара; не обовязкова, але залишимо її для зручності редагування)

Нова версія cal визначає кількість аргументів, обробляє назви місяців і викликає справжню програму cal Мінлива оболонки $ # зберігає кількість аргументів, з яким був викликаний командний файл Інші спеціальні змінні оболонки перераховані в табл 51

Таблиця 51 Вбудовані змінні оболонки

Мінлива

Сенс

$#

$*

$@

$–

$

$

$

$HOME

$IFS

$MAIL

$PATH

$PS1

$PS2

кількість аргументів всі аргументи

аналогічно $ *, див розділ 57 параметри, передані оболонці

повертає код завершення останньої виконаної команди ідентифікатор процесу оболонки

ідентифікатор процесу для останньої команди, запущеної з &

аргумент за замовчуванням для команди cd

список символів, які поділяють слова в аргументах

файл, при зміні якого виводиться повідомлення «you have mail»

список каталогів для пошуку команд

рядок запрошення на введення, за замовчуванням $

рядок запрошення на продовження командного рядка, за замовчуванням>

$ cat  cal

# Cal: поліпшений інтерфейс к / usr / bin / cal case $ # in

case  $m  in

jan*|Jan*)           m=1  ; feb*|Feb*)           m=2  ; mar*|Mar*)           m=3  ; apr*|Apr*)           m=4  ; may*|May*)           m=5  ; jun*|Jun*)           m=6  ; jul*|Jul*)           m=7  ; aug*|Aug*)           m=8  ; sep*|Sep*)           m=9  ; oct*|Oct*)           m=10  ; nov*|Nov*)           m=11  ; dec*|Dec*)           m=12  ;

[1-9] | 10 | 11 | 12); # Числове представлення місяці

*) Y = $ m m = “;; # Тільки рік esac

/ Usr / bin / cal $ m $ y # запустити справжню програму

$

Перший оператор case перевіряє, скільки задано аргументів ($ #), і вибирає відповідну дію Останній шаблон першого оператора case (*) – це «пастка», якщо кількість аргументів не дорівнює ні 0, ні 1, то виконується останній оператор case (Шаблони проглядаються зверху вниз, тому такий збирає все шаблон повинен бути останнім) Він привласнює змінним m і y значення місяця і року Отримавши два ці аргументу, нова версія cal діє так само, як і вихідна

У першому блоці оператора case присутній такий оператор:

set `date`

За зовнішнім виглядом важко визначити, що робить цей оператор, але, якщо виконати його, все стане очевидним:

$ date

Sat  Oct   1 06:05:18  EDT  1983

$ set  `date`

$ echo

Sat

$ echo $4

06:05:20

$

Команда set вбудована в оболонку, і це команда, яка виконує дуже багато дій За відсутності аргументів вона відображає значення змінних оточення, як було показано в розділі 3 Одиночні аргументи встановлюють значення змінних $ 1, $ 2 і т д Таким чином, set `date` встановлює $ 1 в день тижня, $ 2 в назву місяця і т д Тому перший оператор case програми cal уста навливает поточний місяць і рік у разі відсутності аргументів якщо

ж заданий один аргумент, то він сприймається як місяць, а рік береться з поточної дати

Команда set також розпізнає різні параметри, найпоширенішими з них є-v і-x вони включають режим відображення на терміналі команд по мірі їх обробки оболонкою Ці пара метри необхідні для налагодження складних програм

Залишається перетворити назва місяця в текстовій формі в номер Таку операцію виконує другий оператор case, який практично не потребує пояснень, все і так очевидно Єдина тонкість полягає у використанні в шаблонах символу |, який, як і в egrep, позначає альтернативу: big | small відповідає або big, або small Звичайно ж, можлива і запис [jJ] an * і т п Програма допускає введення всіх букв назви місяця в нижньому регістрі (більшість команд сприймають введення в нижньому регістрі) або ж перша буква назви може бути заголовної (саме в такому форматі виводить дані команда date) У табл 52 пояснено, яким чином встановлюється відповідність кожному з шаблонів оболонки

Таблиця 52 Шаблони оболонки

Символ

Відповідність

*

[ccc] &quot…&quot

\c

a|b

/

відповідає будь-якому рядку, в тому числі і порожній відповідає будь-якому окремому символу відповідає будь-якому із символів в ccc

[A-d0-3] еквівалентно [abcd0123]

точно відповідає ..; лапки захищають спеціальні символи

Аналогічно діє …’

буквально відповідає з

(Тільки для операторів case) відповідає або a, або b

для імен файлів відповідає тільки явного знаку / у вираженні для оператора case обробляється подібно до звичайних символам

будучи першим символом імені файлу, відповідає тільки явною

у вираженні

Два останніх розглянутих випадку оператора case аналізують єдиний аргумент, який міг би бути роком (згадайте, що перший оператор case припускав, що це місяць) Якщо це число, яке може представляти місяць, воно не обробляється Інакше вважається, що це рік

Нарешті, останній рядок викликає / usr / bin / cal (тобто справжню cal) з перетвореними аргументами Нова версія cal робить те, що очікує від неї людина, вперше зіткнувся з такою програмою:

$ date

Sat  Oct   1 06:09:55  EDT  1983

$ cal

October  1983

S   M  Tu    W  Th    F    S 1

2   3   4   5   6   7   8

9 10 11 12 13 14 15

16 17 18 19 20 21 22

23 24 25 26 27 28 29

30 31

$ cal  dec

December  1983

S   M   Tu   W   Th   F   S

1   2   3

4   5   6   7   8   9 10

11 12 13 14 15 16 17

18 19 20 21 22 23 24

25 26 27 28 29 30 31

$

А команда cal 1984 виводить календар на весь 1984 год

Нова програма робить те ж саме, що і початкова, але більш простим і легким для сприйняття способом Тому ми вирішили назвати її cal, а не calendar (команда з таким імям вже існує) і не ncal (Менше мнемонічне назва) Збереження колишнього імені зручно для користувачів – не треба запамятовувати нові назви, можна продовжувати діяти рефлекторно

І, щоб закінчити з оператором case, звернемо увагу на відмінність правил встановлення відповідності шаблоном оболонки від аналогічних правил в ed і його похідних Адже наявність двох типів шаблонів означає, що необхідно вивчити два набору правил і що їх обробка здійснюється двома фрагментами коду Деякі розбіжності зявилися виключно через невдалого вибору і так і не були виправлені, наприклад немає ніякого пояснення (за винятком сумісності з вже забутим минулим) тому, що в ed відповідність будь-якому символу задається за допомогою «», а в оболонці – «» Але є й шаблони, що виконують різні завдання Регулярні вирази редактора шукають символьну рядок, яка може зустрітися в будь-якому місці рядка, а для «привязки» пошуку до початку і кінця рядка використовуються спеціальні символи ^ І $ Однак для імен файлів хотілося б мати таку привязку за замовчуванням (оскільки це найпоширеніший випадок) Вводити

$ ls ^ * c $ У такому вигляді не працює

замість

$ ls *c

було б дуже незручно

Вправа 51 Якщо користувачі воліють вдосконалену вами нову версію cal, то як зробити її глобально доступною Що треба зробити для того, щоб помістити її в / usr / bin ~

Вправа 52 Чи варто підправити cal таким чином, щоб cal 83 виводила календар на 1983 год Якщо так, то як тоді вивести календар на 83 рік ~

Вправа 53Змініть cal так, щоб можна було задавати відразу декілька місяців, наприклад

$ cal  oct  nov

або діапазон місяців:

$ cal  oct  dec

Якщо зараз грудень, і вводиться команда cal jan, то календар повинен бути виведений для січня поточного або наступного року Коли ж треба зупинитися і припинити покращувати cal ~

Джерело: Керниган Б, Пайк Р, UNIX Програмне оточення – Пер з англ – СПб: Символ-Плюс, 2003 – 416 с, Мул

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*