Программируемые инструменты
Множество инструментов группируется вокруг языков специального назначения. Программа grep – всего лишь одна из целого семейства инструментов, которые используют регулярные выражения или другие языки для разрешения программистских проблем.
Одним из первых подобных инструментов стал командный интерпретатор, или язык управления заданиями. Достаточно быстро стало понятно, что последовательность команд можно поместить в отдельный файл, а потом запустить экземпляр интерпретатора команд, или оболочки (shell), указав этот файл в качестве источника ввода. Следующим шагом стало уже добавление параметров, условных выражений, циклов, переменных и т. п., то есть всего того, из чего в нашем представлении состоит нормальный язык программирования.
Единственное отличие заключалось в том, что существовал только один тип данных – строки, а операторами в программах-оболочках являлись различные программы, осуществлявшие порой достаточно интересные вычисления. Несмотря на то что программирование под конкретные оболочки сейчас уже уходит в прошлое, уступая место работе с инструментами типа Perl в командных средах или щелканью по кнопкам в графических средах, этот "старинный" подход по-прежнему остается простым и достаточно эффективным способом создания каких-то сложных операций из простых частей.
Еще один программируемый инструмент, Awk, представляет собой небольшой специализированный язык, который предназначен для отбора и преобразования элементов входного потока; он ищет в этом потоке соответствия заданным шаблонам, а когда находит, то выполняет связанные с шаблонами действия. Как мы уже видели в главе 3, Awk автоматически читает входные файлы и разделяет каждую прочитанную строку на поля, обозначаемые от $1 до $NF, где NF есть количество полей в строке. Его поведение "по умолчанию" удобно для выполнения большого числа типовых действий, поэтому многие полезные программы пишутся на Awk в одну строчку. Так, например, программа:
# split.awk: расщепляет текст на отдельные слова { for (i = 1; i <= NF; i+3-) print $i }
Выводит "слова" по одному в строке. И напротив, вот программа fmt, которая заполняет каждую выводимую строку словами (до 60 символов); пустая строка означает конец параграфа:
Мы часто используем fmt для того, чтобы заново разбить на абзацы почтовые сообщения и другие короткие документы; ее же мы использовали главе 3 для форматирования вывода программы markov.
Программируемые инструменты часто берут свое начало от малых языков программирования, созданных для более простого выражения шений проблем в какой-то узкой предметной области. Прелестным примером является инструмент Unix под названием eqn, который обрабатывает математические формулы. Язык, применяемый в нем для ввода, очень похож на обычный: например, выражение f мы прочитали бы вслух как "пи на два" (pi over two), и в этом языке оно так и записывается – pi over 2. Тот же подход применяется и в ТЕХ, в нем это выражениe было бы записано как \pi \over 2. Если для проблемы, которую вы пытаетесь разрешить, уже существует естественный или привычный:особ записи, используйте его или, на худой конец, попробуйте его дотировать: не пытайтесь писать с нуля.
Awk развился из программы, которая использовала регулярные выражения для выявления аномалий в записях телефонного трафика; теперь же Awk содержит в себе переменные, выражения, циклы и т. п., – и это делает его полноценным языком программирования. Perl и Tel первоначально проектировались с целью совместить удобство и выразительность малых языков с мощью полноценных языков программирования. В результате получились действительно удобные языки программирования общего назначения, хотя, конечно, чаще всего их используют для обработки текста.