Про офигительные циркули. Порой бывает устанавливаешь какую нибудь софтину на linux, а впридачу с ней идет огромный example конфиг. Этим конфигом можно пользоваться по дефолту, либо тонко настраивать. Например, конфиг от php.ini весит 80 килобайт. И больше половины в этом конфиге - комментарии и шляпа.



А хочется сделать из этого конфига простенький шаблон например для ansible, но без лишнего мусора. Чтобы было основное, что позволит софтине вообще запуститься (пути, логи, сокеты и т.п.). Руками выкашивать 60-70 килобайт, то еще занятие.



Но что если сделать свой собственный маленький парсер? Который выкосит все ненужное и оставит необходимый минимум. Да, прям на bash! Погнали зажигать!



Для примера будем работать с тем же файлом php.ini и приведем его в юзер-френдли вид.



Накидываем скрипт:



#!/bin/bash



sep=$2



while IFS= read -r var

do

[[ $var =~ ^$sep.* ]] || [[ ! $var =~ ' ' ]] && continue

echo "$var" >> $1.tpl

done < $1



Запускаем так:



./script.sh php.ini ";"



Передаем 2 параметра. Первый = имя файла-конфига, который будем читать и парсить. Второй = символ, которым комментируются строки в этом файле.



В моем случае комментарии в файле идут после «;» символа. Обращаем внимание, что второй параметр передаем в кавычках. Если передать напрямую, то оболочка bash не поймёт что от нее хотят и выпадет в panic.



Разбираем скрипт:



Присваиваем переменной sep, символ, который передали вторым параметром $2. У меня это символ «;».



Далее идет цикл, который построчно читает файл php.ini переданный в первом параметре $1 при запуске скрипта. Тут универсально, можешь любой файл передать, скрипт его сам схавает как нужно.



IFS= разделяет строку с использованием символа в качестве значения



Ну и логика цикла:



Если первый символ равен символу «;», который уже лежит в переменной sep ИЛИ первый символ равен пустой строке, ТО передаем управление команде continue, которая проигнорирует запись в output файл. И так по кругу, пока не закончится файл.



Команда continue пропускает оставшиеся команды внутри тела цикла для текущей итерации и передает управление программой к следующей итерации цикла.



Символ || означает = ИЛИ



ВО ВСЕХ ДРУГИХ СЛУЧАЯХ, происходит запись в output файл, в котором будут содержаться только необходимые для работы параметры.



На выходе получится килобайтный файл php.ini.tpl, без комментариев и прочего шлака. Чистый как слеза.



80 килобайт vs 2 килобайта! Ха! Разница ощутима, теперь можно сделать шаблончик для ansible/puppet/chef.



В своем скрипте я использую простые регулярные выражения. ДА! В bash это можно делать через символы «=~».



$var =~ ^$sep.*



^ = соответствует началу текстовой строки

$sep = символ с помощью которого комментируют строки

.* = оставшийся кусок строки



А можно еще другим способом определять начинается ли строка с определенного символа. Но конкретно с разделителями «;»/«#» это будет работать не корректно.



[[ $var = Y* ]] && echo "String start with Y"



В примере выше, происходит проверка, является ли первый символ в строке символом «Y» и если да, то пезда, выводится соответствующее сообщение. Регулярок тут нет, чисто «*» правит балом.



Такие дела. И без применения всяких sed/бред/винегрет. Нативно, на bash, даже с регулярками научились взаимодействовать, а регулярки развязывают на многое руки. В пределах разумного, не нужно brainfuck создавать.



Brainfuck — один из эзотерических языков программирования, придуман Урбаном Мюллером



Я рассмотрел ситуацию с созданием шаблона, но этот метод парсинга применим вообще под любые задачи, где нужно определить является ли первый символ тем, который тебе нужен. Бери на вооружение.



Завтра сделаем паузу, а в четверг и в пятницу еще немного поэкспериментируем. Давай! Пока-пока!



tags: #bash



💩 @bashdays