Скриптовые языки и обработка текстов

Базис

Алгоритм + структура данных = программа.

  • (примем это за рабочую гипотезу)
  • Текстовое представление исходных кодов программ — для человека

  • Произвольное представление исходных данных — только для роботов?

Тезиc

Данные тоже должны быть текстовыми

  • (примем это за рабочую гипотезу)
  • Текстовый поток управления; пример: команды и командная строка

  • Текстовые пространства имён данных; пример: экспансия файлового подхода, /proc

  • По возможности — текстовые денные; пример: конфигурационные файлы, XPM

    • Вариант — преобразованные в текст; пример hexdump

Антитезис

Что же, всё теперь руками делать?

  • Основной элемент командной строки ОС —­программа. Программа сама себя не запустит, и результатов своей работы не обработает!
  • Предположим, исходные данные не текстовые. Мы их преобразовали в текст, посмотрели, а дальше что?

Синтез

Пускай текст управляет текстом!

  • Языки склейки и алгоритмически полные командные интерпретаторы
    • Более точно: язык склейки (скриптовой) — язык программной манипуляции интерфейсами прикладной среды.
    • В нашем случае — текстовыми

      • Конкретный случай: unix shell, в котором в качестве среды выступает множество утилит (программ) и файлы.

  • Всевозможные языки обработки текстов:
    • Языки контекстной обработки (например, основанные на регулярных выражениях)
    • Макрообработка

Выглядит как план целого С/К, правда?

Командная оболочка

Глава из учебника Unix shell как язык склейки:

  1. Среда: утилиты и файлы *nix-подобной системы
  2. Интерфейс — командная строка
    • В действительности, современный шелл (например, bash) — ЯП, интерпретатор командной строки и язык склейки одновременно

Особенности:

  • Команды — программы, запуск по имени, $PATH
  • Перенаправление ввода-вывода, конвейерная обработка
  • Текстовые переменные, подстановка вывода
  • Запуск процессов в фоне, обработка ошибок и условные операторы
  • Минимализация синтаксиса для основных задач скриптования

Кроме того:

  • Диалекты shell
  • Принцип совмещения интерпретатора, ЯП и оболочки

Контекстная обработка

Нужно много инструментов по обработке текстов!

  • Анализаторы и преобразователи размеченных тестов в стандартных форматах (например, конфигурационных файлов)
  • Анализаторы и преобразователи структурированных гладких текстов — вывода утилит, произвольных конфигурационных файлов, самих скриптов и т. п.

  • Принцип контекстной адресации

    Программа состоит из блоков, каждый из которых обрабатывает заданную часть текста

    • Чаще всего текст читается построчно
      • строки обычно достаточно
      • строка — неплохой контекст для РВ

Регулярное выражение

(нужно не менее лекции, так что не сейчас)

  • Мощный инструмент анализа/преобразования текста
  • Требует строгого ограничения контекста (пример: поиск строковой константы а ЯП)
  • имеет 100500 диалектов ☺

Макроподстановка

Задача: параметризовать текст.

  • Подставить пути до каталогов
  • Вставить шаблон (вместо короткого текста — длинный)
  • Вставить параметрический шаблон

  • Вставить шаблон, параметры которого, как оказалось, тоже шаблоны ☺
  • Вставить текст/шаблон в зависимости от условия
  • Преобразовать строки
  • Работать с файлами
  • Отказаться от построчной обработки

Самый популярный вариант — препроцессор Си и другие макронадстройки над языками.

M4

Чуть ли не единственный из известных.

Принцип:

  • На входе — текст, содержащий команды M4
  • Каждая команда, по мере поступления, выполняется, подставляя вместо себя результат своего выполнения (операция макроподстановки)
  • Этот результат может, в свою очередь, содержать команды M4, поэтому анализ текста возобновляется с позиции, в которую была сделана подстановка
  • На выходе — текст, не содержащий команд M4

Вот этот текст разумный http://mbreen.com/m4.html

Примеры просьба прощёлкивать! Если нет linux под рукой — можно воспользоваться любым online linux-окружением, например http://repl.it. При открытии редактора там в правой части запускается натуральная linux-консоль.

В ней можно запустить m4, но лучше что-нибудь вроде cat > o; echo "===="; m4 < o, чтобы ввод и вывод не перемешивались. Ввод заканчивается новой строкой и Ctrl+D для обозначения конца файла.

Макроопределение и макроподстановка

define(AUTHOR, W. Shakespeare)
`AUTHOR' is AUTHOR
  • Однако

define(AUTHOR, Me)
define(AUTHOR, A. Maclean)
`AUTHOR' is AUTHOR or Me?
  • А это не заработает:

define(AUTHOR, W. Shakespeare)
define(AUTHOR, A. Maclean)
`AUTHOR' is AUTHOR
  • Так что лучше брать макрос в кавычки всегда, и обмазывать dnl от лишних переводов строки

define(`AUTHOR', Me)dnl
define(`AUTHOR', A. Maclean)dnl
`AUTHOR' is AUTHOR or Me?

Вложенность кавычек

define(`definenum', `define(`num', `99')')
num
definenum
num
  • В то время как

define(`definenum', define(`num', `99'))
num

Условные операторы

ifdef()

Только на сопоставление

define(`a', b)dnl
ifelse(a, b, c, d)
ifelse(a, B, c, d)
  • и похитрее

define(`a', d)dnl
define(`e', b)dnl
ifelse(a, b, b-true, c, c-true, d, d-true, all-false)
ifelse(e, b, b-true, c, c-true, d, d-true, all-false)

Типы данных

  • eval() — вычисление арифметических выражений

  • translit(), index(), substr(), len(), regex(), … — строки

translit(`Highgest leet of all', `etl', 371)
  • (кавычки можно не ставить, но мало ли: слева точно литералы, а справа может быть и макро)

Параметрические макросы и циклы

Параметры — это просто $№ в теле макроподствновки

  • $# — количество, $* — все сразу, $@ — все сразу, но закавыченные (без дальнейшей макроподстановки)

define(`NONTERM', non-terminal)dnl
define(`param', `All: $*
All-quoted: $@
Number: $#; Second: $2')dnl
param(one, two by two, NONTERM, three)
param(`one', `two by two', `NONTERM', `three')

Цикл == рекурсия!

  • define(`len',`ifelse($1,,0,`eval(1+len(substr($1,1)))')')dnl
    len(qw qw)
    len()
    len

Остальные циклы (forloop, foreach cмоделированы в соотв. библиотеках)

Потоки вывода

Часть текста можно перенаправить в синтетический поток, по окончании работы M4 они припишутся в конец в порядке нумерации (0 — основной поток)

one
divert(3)dnl
two
three
divert(1)dnl
four
five
divert(0)dnl
six
seven

Поток -1 не направляется никуда (а определённые макросы остаются!), а ещё поток можно закрыть и вставить по месту с помощью undivert()

divert(-1)
Здесь можно писать что угодно
значение имеют только макроопределения
define(`c', > $1)
divert(0)dnl
c(выхожу один)
divert(1)dnl
c(я на дорогу)
divert(0)dnl
c(сквозь туман)
undivert(1)dnl
тернистый путь блестит

Далее везде…

  • pushdef() и стеки определений (смена контекста)

  • Поддержка примитивов склейки (system())

  • Набор библиотек
  • Макровзрыв

Фактически, декларативный алгоритмически полный язык

Потоковый редактор sed

Общая структура программы список инструкций вида:

  • <контекстный_адрес><команда>
    <контекстный_адрес><команда>
    
  • Обработка текста идёт построчно
  • Каждая строка, удовлетворяющая контекстному адресу, обрабатывается командой

Контекстный адрес:

  • номер строки или $

  • номер строки~шаг

  • /РВ/ (или \∀РВ∀, где — любой)

  • адрес,адрес — от, до

Команды:

  • d — удалить строку, a/i — добавить несколько, с — заменить

  • y/что/на что/ — преобразование символов по аналогии с tr

  • поиск с заменой в строке: s/РВ/подстановка/

  • Условный оператор: t метка — если предыдущая замена была успешна

    • безусловный переход: b метка

    • собственно, метка: : метка

  • работа с буфером: g G h H x

  • {} — группировка инструкций в одну команду

  • всякое

Примеры:

  • cal | sed -E 's/[^[:digit:][:space:]_]/@/g'

  • ldd /lib64/lib*.so.* | sed -n '/^\//h;/libcrypto.*=/{x;p;x;p}'

  • locate .sed — любой)

Алсо, полнота по Тюрингу повсюду

AWK

Общая структура программы список инструкций вида:

  •  <контекстный_адрес> { <список команд> }
     <контекстный_адрес> { <список команд> }
  • Обработка текста идёт построчно
  • Каждая строка, удовлетворяющая контекстному адресу, обрабатывается командами из списка

Команды реализуют Си-подобный синтаксис

  • Все переменные текстовые, численное преобразование автоматическое
  • Ассоциативные массивы
  • Строка автоматически разбивается на слова:

    • Доступны в переменных $1, $2, …; $0 — вся строка

    • Можно переопределять разделители полей (и строк!)
  • Операция склейки строк: «"str1" "str2"» = «"str1str2"»

Контекстный адрес:

  • выражение — строка удовлетворяет такому адресу, если выражение не пусто и не 0

    • можно использовать конструкцию выражение~/РВ/!~)

  • /РВ/ (фактически $0~/РВ/

  • BEGIN, END (до начала, после конца файла)

  • пустой (для всех строк)
  • Двухадресный — диапазон

Примеры:

GAWK

Примеры

  • Про склейку: cal | awk '/1/{print | "sort" }; /9/{print | "sort" }'

  • locate .awk

Фактически, полноценный ЯП, на котором бы много писали, если бы не …

Perl

Не пойдём дальше Википедии

  • ЯП общего назначения
  • Имеет неплохую объектную модель и структуру типов
  • Поддерживает контекстную адресацию
  • Поддерживает примитивы склейки
  • CPAN огромная библиотека модулей

  • Минималистичный и очень гибкий синтаксис
  • Стремительно теряет популярность ☹

???

Парадигмы программирования и программирование как род деятельности

«Программирование» — что это?

Нельзя объять необъятного!

Д/З

Подробности — на странице курса

LecturesCMC/AL/2020_11_30 (последним исправлял пользователь FrBrGeorge 2020-11-29 16:43:37)