Скриптовые языки и обработка текстов
- Базис
Алгоритм + структура данных = программа.
- (примем это за рабочую гипотезу)
Текстовое представление исходных кодов программ — для человека
Произвольное представление исходных данных — только для роботов?
- Тезиc
Данные тоже должны быть текстовыми
- Антитезис
Что же, всё теперь руками делать?
- Основной элемент командной строки ОС —программа. Программа сама себя не запустит, и результатов своей работы не обработает!
Предположим, исходные данные не текстовые. Мы их преобразовали в текст, посмотрели, а дальше что?
- Синтез
Пускай текст управляет текстом!
- Языки склейки и алгоритмически полные командные интерпретаторы
- Более точно: язык склейки (скриптовой) — язык программной манипуляции интерфейсами прикладной среды.
В нашем случае — текстовыми
Конкретный случай: unix shell, в котором в качестве среды выступает множество утилит (программ) и файлы.
- Всевозможные языки обработки текстов:
- Языки контекстной обработки (например, основанные на регулярных выражениях)
- Макрообработка
- Языки склейки и алгоритмически полные командные интерпретаторы
Выглядит как план целого С/К, правда?
Командная оболочка
Глава из учебника Unix shell как язык склейки:
- Среда: утилиты и файлы *nix-подобной системы
- Интерфейс — командная строка
- В действительности, современный шелл (например, bash) — ЯП, интерпретатор командной строки и язык склейки одновременно
Особенности:
- Команды — программы, запуск по имени, $PATH
- Перенаправление ввода-вывода, конвейерная обработка
- Текстовые переменные, подстановка вывода
- Запуск процессов в фоне, обработка ошибок и условные операторы
- Минимализация синтаксиса для основных задач скриптования
- …
Кроме того:
- Диалекты shell
- Принцип совмещения интерпретатора, ЯП и оболочки
Контекстная обработка
Нужно много инструментов по обработке текстов!
- Анализаторы и преобразователи размеченных тестов в стандартных форматах (например, конфигурационных файлов)
Анализаторы и преобразователи структурированных гладких текстов — вывода утилит, произвольных конфигурационных файлов, самих скриптов и т. п.
- Принцип контекстной адресации
Программа состоит из блоков, каждый из которых обрабатывает заданную часть текста
- Чаще всего текст читается построчно
- строки обычно достаточно
- строка — неплохой контекст для РВ
- Чаще всего текст читается построчно
Регулярное выражение
(нужно не менее лекции, так что не сейчас)
- Мощный инструмент анализа/преобразования текста
- Требует строгого ограничения контекста (пример: поиск строковой константы а ЯП)
- имеет 100500 диалектов ☺
Макроподстановка
Задача: параметризовать текст.
- Подставить пути до каталогов
- Вставить шаблон (вместо короткого текста — длинный)
Вставить параметрический шаблон
- Вставить шаблон, параметры которого, как оказалось, тоже шаблоны ☺
- Вставить текст/шаблон в зависимости от условия
- Преобразовать строки
- Работать с файлами
- …
Отказаться от построчной обработки
Самый популярный вариант — препроцессор Си и другие макронадстройки над языками.
M4
Чуть ли не единственный из известных.
Macro Magic: M4 Complete Guide 2019 года
учебник в составе autoconf (обратите внимание: в autoconf кавычки переопределены в [ и ])
Принцип:
- На входе — текст, содержащий команды 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
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
История (фамилии какие!)
- Там же неплохие короткие примерчики
Старые учебники на русском: очень старый, тоже очень старый
GAWK: Документация, перевод
Общая структура программы список инструкций вида:
<контекстный_адрес> { <список команд> } <контекстный_адрес> { <список команд> }
- Обработка текста идёт построчно
- Каждая строка, удовлетворяющая контекстному адресу, обрабатывается командами из списка
Команды реализуют Си-подобный синтаксис
- Все переменные текстовые, численное преобразование автоматическое
- Ассоциативные массивы
Строка автоматически разбивается на слова:
Доступны в переменных $1, $2, …; $0 — вся строка
- Можно переопределять разделители полей (и строк!)
Операция склейки строк: «"str1" "str2"» = «"str1str2"»
- …
Контекстный адрес:
выражение — строка удовлетворяет такому адресу, если выражение не пусто и не 0
можно использовать конструкцию выражение~/РВ/ (и !~)
/РВ/ (фактически $0~/РВ/
BEGIN, END (до начала, после конца файла)
- пустой (для всех строк)
- Двухадресный — диапазон
Примеры:
ldd /lib64/lib*.so.* | awk '/^\//{F=$1};/libcrypto.*=/{print(F, $3)}'
Наиболее востребованная особенность — полноценный поиск с заменой (gensub())
Поддержка склейки (например, прозрачное перенаправление В/В,
Много функций (на уровне ЯП общего назначения)
- Библиотеки
- …
Примеры
Про склейку: cal | awk '/1/{print | "sort" }; /9/{print | "sort" }'
locate .awk ☺
Фактически, полноценный ЯП, на котором бы много писали, если бы не …
Perl
Не пойдём дальше Википедии
- ЯП общего назначения
- Имеет неплохую объектную модель и структуру типов
- Поддерживает контекстную адресацию
- Поддерживает примитивы склейки
CPAN огромная библиотека модулей
- Минималистичный и очень гибкий синтаксис
- …
- …
- Стремительно теряет популярность ☹
???
Парадигмы программирования и программирование как род деятельности
«Программирование» — что это?
- Формализация алгоритма
- Анализ прикладной задачи, построение её модели и решение этой задачи на модели
- Разработка программного продукта
Совместная разработка программного продукта
- …
https://en.wikipedia.org/wiki/List_of_software_development_philosophies
Нельзя объять необъятного!
Д/З
Подробности — на странице курса