Командні мови та командні інтерпретатори
Командні мови та командні інтерпретатори
Як і в більшості інтерактивних систем, традиційний інтерфейс з користувачем ОС UNIX базується на використанні командних мов. Висловлюючись дещо тавтологічно, можна сказати, що командна мова - це мова, якою користувач взаємодіє з системою в інтерактивному режимі. Така мова називається командною, оскільки кожен рядок, що вводиться з терміналу та відправляється системі, можна розглядати як команду користувача по відношенню до системи. Одним із досягнень ОС UNIX є те, що командні мови цієї операційної системи є добре визначеними (не дуже хороший український термін, що відповідає абсолютно однозначному англійському терміну well-defined) та містять багато засобів, що наближають їх до мов програмування.
Особливістю командних мов є те, що в більшості випадків вони не використовуються для програмування в звичайному значенні цього слова, хоча розвиненою командною мовою можна написати будь-яку програму. На нашу думку, правильним стилем використання командної мови є його застосування в основному для безпосередньої взаємодії із системою із залученням можливостей складання командних файлів (скриптів або сценаріїв у термінології ОС UNIX) для економії повторюваних рутинних процедур.
Програми, призначені обробки конструкцій командних мов, називаються командними інтерпретаторами. На відміну від компілюваних мов програмування (таких як Сі або Паскаль), для кожного з яких зазвичай існує багато різних компіляторів, командна мова, як правило, нерозривно пов'язана з відповідним інтерпретатором. Коли нижче ми говоритимемо про різних представників командних мов ОС UNIX, що належать до сімейства shell,то щоразу під однойменною назвою ми розумітимемо і відповідний інтерпретатор.
Загальна характеристика командних мов
У цьому пункті і далі в цьому розділі ми більш конкретно говоритимемо про командні мови сімейства shell. Основне призначення цих мов (їх різновидів існує досить багато, але ми розглянемо лише три найбільш поширені варіанти - Bourne-shell, C-shell та Korn-shell) полягає в тому, щоб надати користувачам зручні засоби взаємодії із системою. Що це означає? Мови недаремно називаються командними. Вони призначені для того, щоб надати користувачеві можливість виконувати команди, призначені для виконання деяких дій операційної системи. Існує два види команд.
Власні команди shell (такі як cd, echo, exec тощо) виконуються безпосередньо інтерпретатором, тобто. їхня семантика вбудована у відповідну мову. Імена інших команд насправді є іменами файлів, що містять програми, що виконуються. У разі виклику такої команди, інтерпретатор командної мови з використанням відповідних системних викликів запускає паралельний процес, в якому виконується потрібна програма. Звісно, сенс дії подібних команд досить умовним, оскільки залежить від конкретного наповнення зовнішніх файлів. Тим не менш, в описі кожної мови містяться і характеристики "зовнішніх команд" (наприклад, find, grep, cc і т.д.) для того, що розсудливі користувачі (і їх адміністратори) не змінюватимуть вміст відповідних файлів.
Істотним компонентом командної мови є засоби, що дають змогу різноманітними способами комбінувати прості команди, утворюючи на їх основі складові команди. У сімействі мов shell можливітакі засоби комбінування. В одному командному рядку (важливий термін, що означає одиницю інформаційної взаємодії з командним інтерпретатором), можна вказати список команд, які повинні виконуватися послідовно, або список команд, які повинні виконуватися "паралельно" (тобто незалежно одна від іншої).
Дуже важливою особливістю сімейства мов shell є можливості перенаправлення вводу/виводу та організації конвеєрів команд. Звичайно, ці можливості спираються на базові засоби ОС UNIX (див. п. 2.1.8). Стисло нагадаємо, у чому вони полягають. Для кожного процесу користувача (а зовнішні команди shell виконуються в рамках окремих користувальницьких процесів) визначено три виділені дескриптори файлів: файл стандартного введення (standard input), файл стандартного виведення (standard output) і файл стандартного виведення повідомлень про помилки (standard error). Хорошим стилем програмування в середовищі ОС UNIX є такий, при якому будь-яка програма читає свої вступні дані з файлу стандартного введення, а виводить свої результати та повідомлення про помилки у файли стандартного виводу та стандартного виведення повідомлень про помилки відповідно. Оскільки будь-який породжений процес "успадковує" всі відкриті файли свого предка (див. п. 2.1.7), то при програмуванні команди рекомендується не замислюватися про джерело вступної інформації програми, а також конкретний ресурс, що підтримує виведення основних повідомлень та повідомлень про помилки. Потрібно просто користуватися стандартними файлами, за конкретне визначення яких відповідає процес-предок (зауважимо, що за замовчуванням усі три файли відповідають введенню та виведенню на той термінал, з якого працює користувач).
Що забезпечує така дисципліна роботи? Насамперед можливість створенняпрограм, "нейтральних" по відношенню до джерела своїх вступних даних та призначення своїх вивідних даних. Власне, на цьому й ґрунтуються принципи перенаправлення вводу/виводу та організації конвеєра команд. Все дуже просто. Якщо ви пишете в командному рядку конструкцію
com1 par1, par2, . parn > file_name ,
це означає, що для стандартного виведення команди com1 буде використовуватися файл з ім'ям file_name. Якщо ви пишете