Чтение онлайн

ЖАНРЫ

Искусство программирования для Unix
Шрифт:

Язык XSLT, который используется для описания трансформаций XML-файлов, соответствует верхнему уровню сложности декларативных мини-языков. Он довольно сложен для того, чтобы рассматривать его как мини-язык, однако разделяет некоторые важные характеристики таких языков, которые подробнее рассматриваются ниже при изучении XSLT.

Спектр мини-языков простирается от декларативных (с неявными действиями) к императивным (с явными действиями). Синтаксис файла конфигурации программы fetchmail(l) можно рассматривать либо как очень слабый императивный язык, либо как декларативный язык с неявной управляющей логикой. Языки обработки

текстов troff и PostScript являются императивными языками с большим количеством встроенной специальной информации о прикладной области.

Некоторые императивные мини-языки для решения специальных задач граничат с универсальными интерпретаторами. Они достигают данного уровня, когда явно являются языками Тьюринга, т.е. они могут выполнять условные операции и циклы

(или рекурсию)58 с функциями, которые предназначены для использования в качестве управляющих структур. В отличие от них, некоторые языки только отчасти являются языками Тьюринга. В них имеются функции, которые можно использовать для реализации управляющих структур как побочный эффект того, для чего они фактически предназначены.

Интерпретаторы Ьс(1) и dc(1), рассмотренные в главе 7, являются хорошими примерами специализированных императивных мини-языков, которые явно являются языками Тьюринга.

Такие языки, как Emacs Lisp и JavaScript, находятся в области универсальных интерпретаторов. Языки Emacs Lisp и JavaScript предназначены для использования в качестве полных языков программирования, работающих в специализированных средах. Более подробно они описываются ниже при рассмотрении встроенных языков сценариев.

Область интерпретаторов представляет собой область возрастающей неопределенности. Оборотной стороной этого является то, что более универсальный интерпретатор включает в себя меньше предположений о среде, в которой он работает. С возрастающей неопределенностью обычно приходит более развитая онтология типов данных. Shell и Tel обладают сравнительно простой онтологией, a Perl, Python и Java — более сложной. Данные универсальные языки подробнее рассматриваются в главе 14.

8.2. Применение мини-языков

Разработка программ с помощью мини-языков затрагивает две отдельные проблемы. Одна из них заключается в том, чтобы уметь пользоваться имеющимися в инструментарии мини-языками и понимать, когда их можно применять такими, как они есть. Другая проблема — знать, когда целесообразно разрабатывать для приложения нестандартный мини-язык. Для того чтобы помочь читателю развить оба аспекта конструкторского мышления, почти половина данной главы состоит из учебных примеров.

8.2.1. Учебный пример: sng

В главе 6 рассматривалась утилита sng(1), преобразовывающая PNG-файл в редактируемую полностью текстовую форму. Формат файлов данных SNG заслуживает повторного рассмотрения здесь для контраста, поскольку он не вполне является узкоспециальным мини-языком. Он описывает расположение данных, но не связывает с ними какую-либо предполагаемую последовательность действий.

Однако SNG действительно имеет одну общую важную характеристику с узкоспециальными мини-языками, которую не поддерживают

структурированные двоичные форматы данных, подобные PNG, — прозрачность. Структурированные файлы данных позволяют без использования мини-языка взаимодействовать средствам редактирования, преобразования и создания, которые не имеют информации о конструкторских "предположениях" друг друга. В случае SNG добавляется то, что данный формат как узкоспециальный мини-язык, предназначен для простого просмотра и редактирования с помощью универсальных средств.

8.2.2. Учебный пример: регулярные выражения

Одним из видов спецификации, который периодически появляется в инструментах Unix и языках сценариев, является регулярное выражение (regular expression, или regexp для краткости). Здесь регулярные выражения рассматриваются как декларативный мини-язык для описания текстовых шаблонов. Часто регулярные выражения встраиваются в другие мини-языки. Регулярные выражения настолько распространены, что их едва ли можно считать мини-языком, однако они заменяют то, что в противном случае представляло было собой огромные объемы кода, реализующего различные (и несовместимые) возможности поиска.

В данном введении не рассматриваются такие подробности, как POSIX-расширения, обратные ссылки и особенности интернационализации. Более подробное изложение способа их применения представлено в книге "Mastering Regular Expressions" [22].

Регулярные выражения описывают шаблоны, которые могут либо совпадать, либо не совпадать со строками. Простейшим средством для работы с регулярными выражениями является утилита grep(1), фильтр, который переправляет со стандартного ввода на стандартный вывод каждую строку, соответствующую указанному регулярному выражению. Форма записи регулярных выражений кратко представлена в таблице 8.1.

Существует большое количество второстепенных вариантов записи регулярных выражений.

1. Выражения-маски. Ограниченный набор соглашений по применению символов-шаблонов (wildcard), использовавшийся в ранних оболочках Unix для сопоставления имен файлов. Существует всего 3 символа-шаблона: * — соответствует любой последовательности символов (как . * в других вариантах); ? — соответствует любому единичному символу (как . в других вариантах); [. . . ] — соответствует классу символов как в других вариантах. В некоторых оболочках (csh, bash, zsh) позднее был добавлен шаблон {} для выбора подстроки. Таким образом, выражение x{a,b}c соответствует строкам хас или xbc, но не хс. В некоторых оболочках выражения-маски получили дальнейшее развитие в направлении расширения регулярных выражений.

2. Базовые регулярные выражения. Форма записи, принятая в исходной утилите grep(1) для извлечения из файла строк, соответствующих заданному регулярному выражению. Выражения этого типа также применяются в строковом редакторе ed(1) и потоковом редакторе sed(1). Профессионалы старой школы Unix считают данное выражение основной, или "унифицированной", разновидностью регулярных выражений. Пользователи, впервые столкнувшиеся с более современными инструментами, склонны использовать расширенную форму, которая описана ниже.

Поделиться с друзьями: