Обработка текстов и сценарии
Лекция позапрошлого года на похожую тему
Задача склейки
Командная строка как основной интерфейс управления
⇒ Понятие сценария:
- Использование тех же самых команд
- Алгоритмическая полнота (по возможности)
- Удобная суперпозиция команд (подстановка)
- «Админское программирование»: экономия объёма получающегося текста программы
Почему это часто встречается при сборке? Рецепты в make — это именно сценарии shell!
Простые команды, которые проще написать на шелле, чем городить отдельный синтаксис make
- Нестандартные сценарии и рецепты
- Костыли
Shell
- Интерпретатор командной строки
- редактор командной строки, история, достраивание, alias-ы, …, управление заданиями и многое другое
- ЯП ВУ (функции, условные операторы и циклы, в некоторых шеллах — массивы)
Ориентация на работу с текстом / фалйами / процессами — склейку
Глава из учебника про shell
(Интерпретатор: редактор командной строки, история, достраивание, alias-ы, …, управление заданиями)
ЯП с упором на склейку
- Переменные и их подстановка с простейшей пост-обработкой
Встроенные команды и программы-команды
- ⇒ «Сколько команд в командной строке»?
⇒ управление процессами (& и wait)
- Перенаправление ввода-вывода
Вывод в строковое выражение `команда`, оно же $(команда)
>, < и 2>
>> и <<
|, великий и могучий!
- Условный оператор и циклы
- Exit status как условие
Утилита test (она же — утилита [)
case и шаблоны
- Генерация имён файлов
- Обработка сигналов
- …
Утилиты для работы с файловой системой и процессами
Основная документация: GNU coreutils
- всякая классика типа cp/mv/ls и т. п.
- Пример: как удалять временные файлы:
1 #!/bin/sh 2 exit_handler() { 3 trap - EXIT 4 test -r "$TMPFILE" && rm -vf "$TMPFILE" 5 } 6 7 trap exit_handler EXIT HUP INT QUIT PIPE TERM 8 9 echo -n "Create a file? " 10 read YN 11 if [ "$YN" = y ]; then 12 TMPFILE="`mktemp`" 13 echo "$TMPFILE" 14 ls -l "$TMPFILE" 15 fi 16 echo -n "Wait…" 17 read 18 echo "Done"
- Пример: как удалять временные файлы:
- …
Утилиты работы с текстом
Проблема локали:
Основная документация: GNU coreutils
cut, tr, tail, head, sort, paste, join, их много… (coreutils)
Пример: join
hexdump из Util-linux, xxd из vim и od из coreutils
Just for fun: moreutils
- …
Комбайны
grep для поиска
sed для поиска с заменой:
$ cal | sed 's/\([01]\)\([2-3]\)/\2:\1/g' Октябрь 22:01 Пн Вт Ср Чт Пт Сб Вс 1 2 3 4 5 6 7 8 9 10 11 2:1 3:1 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
awk (или perl) для написания программ, управляемых контекстом
можно и sed, но…
а можно и любой ЯП. но будет длинно
m4…
- …
Д/З
Прочитать и попробовать всё, что вам покажется релевантным задаче из GNU coreutils, возможно, больше
В репозитории с Д/З сделать (вложенный) подкаталог 04_Text, а в нём — сценарий на shell randomize.sh, который принимает один необязательный параметр — время задержки в секундах (вещественное) перед выводом очередного символа, затем читает со стандартного ввода небольшой файл с ASCII-артом в кодировке ASCII и без символов табуляции, после чего выводит его посимвольно в случайном порядке в левый верхний угол экрана. Должен получиться с виду тот же ASCII-арт (аккуратнее с пробелами).
- Что может понадобиться:
- Перенаправление ввода-вывода
tput (cup и clear, было на лекции) из пакета termutils
Арифметика в shell (конструкция вида $((…)))
Параметры командной строки shell-сценария (конструкция вида $1, $2 и т. п.)
Цикл while в shell
- Условие: нельзя пользоваться другими языками программирования (sed-ом можно, но можно обойтись и без него). В идеале
Необязательное дополнение: скрипт должен выполняться стандартным sehll-ом (не bash, а dash, он же ash, например). Я пока нашёл одну неприятность; встроенное echo в ash не умеет -e — пользуйтесь /bin/echo, оно умеет
Необязательное дополнение: научиться работать с псевдографикой и русскими буквами.
- Проблема: русские буквы в UTF8 занимают два байта, а псевдографика — вообще три
- Решение: сначала перекодировать поток в UCS2, например, там всё будет одинаковое
Необязательное дополнение: выводить ASCII-арт посередине экрана
Проблема (неожиданная): посчитать во входном потоке количество строк и максимальную ширину строки легко, а вот передать эти данные перед тем, как передать остальные, данные просто так не получится
- Решение: использовать временный файл только обязательно удалять его
- Что может понадобиться:
Я решал базовую задачу так (спойлер):
Получилось пока вот что:
Извините, не удержался:
(tr) заменил пробелы на ^A (код 01)
(read) считывал ввод в цикле построчно, увеличивая y на 1
(od с правильными ключами) превращал строку в последовательность шестнадцатеричных чисел, по которой проходил ещё одним циклом, увеличивая x на единицу
(echo) каждое такое число (кроме 01) выводил, сопровождая полученными координатами x и y
(shuf) перемешивал строки с тройками чисел
(read) читал перемешанные код, y и x
(tput cup) позиционировал курсор и (echo -ne) выводил символ с кодом
(sleep) ждал. Не забыть очистить экран в начале работы и перевести курсор в нижний угол в конце