# Лабораторная работа №5 "Bash Certification" --- ## **Цели работы:** - Самостоятельно изучить основы программирования на bash. - Приобретение навыка обработки документов MS Office bash-скриптом. --- ## Ход работы ### **Задание:** Для выпускников школы срочно нужно заполнить именные грамоты на каждого ребёнка. Разумеется, с помощью bash. #### Имеется шаблон грамоты (грамота.docx) и список учеников (ФИО.txt) #### **Результат:** bash-скрипт, который создаёт грамоту в формате docx для каждого ученика. Итак, для начала стоит посмотреть сами файлы. 1) ФИО.txt В файле построчно записано по 3 слова - ФИО. ![](https://i.imgur.com/Kv0q24c.png) 2) грамота.docx В файле представлен макет грамоты, в котором надо заменить "ФИО" на значение из первого файла. ![](https://i.imgur.com/SDsmxOZ.png) По началу, была идея заменить строку "ФИО" используя команду "sed", не углубляясь в сам файл. Команда выглядел примерно так: ```bash for FIO in $(cat ФИО.txt); do sed -i "s/ФИО/$FIO/g" грамота.docx > $FIO.gramota.docx; done ``` Но, данная идея оказалась не рабочей от слова совсем, собраные после грамоты не запускались. Пришлось думать дальше. Потом вспомнил, что в отличии о формата doc, docx представляет собой архив. Где необходимый текст содержится в файле /word/document.xml ![](https://i.imgur.com/UcBCB8l.png) ![](https://i.imgur.com/N7SD5xT.png) ![](https://i.imgur.com/IkkBG4o.png) Уже отталкиваясь от этого факта буду работать дальше. Был придуман следующий алгоритм: 1) Разархивировать макет грамоты и использовать его для дальнейшего создания новых архивов. 2) Проходясь в цикле по каждой строке файла с ФИО, заменять значение "ФИО" в файле **/word/document.xml**. 3) Полученный "документ", заархивировать обратно в docx файл. По ходу реализации данной идеи возникло достаточно много ошибок и прочех проблем. Окончательный вариант bash-команды выглядит следующим образом: ```bash unzip грамота.docx -d gramota; IFS=$'\n'; for fio in $(cat ФИО.txt); do cp -R gramota $fio.gramota; sed -i "s/ФИО/$fio/g" $fio.gramota/word/document.xml; cd $fio.gramota/; zip -r $fio.gramota.docx *; cd ../; cp $fio.gramota/$fio.gramota.docx $fio.gramota.docx; rm -rf $fio.gramota/; done; rm -rf gramota ``` Очевидно, это не лучшая реализация, но главное, что она работает. Все грамоты были создано успешно: ![](https://i.imgur.com/9AQquAK.png) ![](https://i.imgur.com/zaostp1.png) ![](https://i.imgur.com/SnFusXg.png) Теперь рассмотрим саму команду подробно: 1) Разархивация макета. ```bash unzip грамота.docx -d gramota; ``` 2) Специальная переменная оболочки "IFS" определяет, как Bash распознает границы слов при разделении последовательности строк символов. По умолчанию IFS представляет собой трехсимвольную строку, состоящую из пробела, табуляции и новой строки. Это значит, что при чтении файла с ФИО, цикл будет проходить не просто по всей строке сразу, а по Имени, Фамилии и Отчеству отдельно - чего нам не нужно. Чтобы исправить это, меняю значение переменной на "новою строку" ```bash IFS=$'\n'; ``` 3) Цикл по каждой строке файла ФИО (т.е. по каждой строке ФИО) ```bash for fio in $(cat ФИО.txt); ``` 4) Копирую папку с макетом, для дальнейшего его изменения: ```bash cp -R gramota $fio.gramota; ``` 5) Суть всей команды именно эта часть - замена строки "ФИО" на строку из файла ФИО.txt. Параметр **"-i"** - указывает о сохранении изменений в файл. За замену строки отвечает структура: **"s/[Строка которую будем заменять]/[Строка на которую будет замена]"** ```bash sed -i "s/ФИО/$fio/g" $fio.gramota/word/document.xml; ``` 6) Теперь архивирую макет обратно в docx файл. Не уверен в причине, но если запускал команду **zip** вне самой папки с файлами, то структура docx файла была нарушена: все файлы находились внутри ещё одной папки, чего быть не дложно. Поэтому пришлось входить в папку и выходить из неё. :::danger ![](https://i.imgur.com/79JZGfF.png) ::: :::success ![](https://i.imgur.com/QVK7VmA.png) ::: ```bash cd $fio.gramota/; zip -r $fio.gramota.docx *; cd ../; ``` 7) Достаю документ из папки и удаляю всё то, что осталось. (Команда **"done"** - конец цикла). И сразу удаляю архивированый в начале макет грамоты. ```bash cp $fio.gramota/$fio.gramota.docx $fio.gramota.docx; rm -rf $fio.gramota/; done; rm -rf gramota ``` --- ### Заключение Вероятно, это не самая удачная реализация команды, но она работает!) За время выполнения лабораторной работы столкнулся с множеством мелких проблем (большая из них связана с **"zip"**), но именно этот факт позволил лучше ознакомиться с bash.