
У меня есть довольно большой проект BASH, который я разделил на несколько файлов, чтобы сделать его более читабельным. В результате основной файл содержит много source
операторов.
Теперь я выкладываю его на GitHub и пишу для него скрипт установщика. Проблема в том, что создание подкаталогов в бинарных папках (именно /usr/local/sbin
) запрещено FHS, а я не хочу засорять бинарные папки несколькими файлами типа main.bash
config.bash
, и т. д.
В качестве решения я подумал, что если скрипт установщика объединит эти файлы, то я получу большой монолитный файл BASH, который можно будет разместить в любом месте системы.
Вопрос в следующем: как мне заменить все source
операторы в моем основном скрипте содержимым исходных файлов?
Пример:
включено.bash
echo "bar"
основной.баш
echo "foo"
source included.bash
Результирующий монолитный файл
echo "foo"
echo "bar"
решение1
Этот скрипт, который может называться make-monolithic.bash
, будет проходить по каждой строке main.bash
и искать source
оператор. Если совпадений нет, он просто скопирует эту строку в monolithic.bash
файл. Однако если source
строка найдена, имя файла извлекается, и содержимое этого файла будет скопировано в monolithic.bash
, вместо исходной source
строки.
#!/usr/bin/env bash
readonly MAIN="main.bash"
readonly MONOLITHIC="monolithic.bash"
[ -f "$MONOLITHIC" ] && cp "$MONOLITHIC" "${MONOLITHIC}.bak"
## to extract sourced filename
regex='^\([[:space:]]*\)source[[:space:]]\+\([^[:space:]]\+\)[[:space:]]*$'
IFS=$'\n' ## retain whitespace
while read main_line; do
sourced=$(echo "$main_line" | sed -n "s/$regex/\2/p")
if [ -n "$sourced" ]; then
indent=$(echo "$main_line" | sed -n "s/$regex/\1/p")
while read sourced_line; do
echo "${indent}${sourced_line}" >> "$MONOLITHIC"
done < "$sourced"
else
echo "$main_line" >> "$MONOLITHIC"
fi
done < "$MAIN"
unset IFS
[ -f "${MONOLITHIC}.bak" ] && rm "${MONOLITHIC}.bak"
- проверено на предоставленном вами примере
- также изящно игнорирует возможные проблемы с пробелами в
source
строке - плюс: автоматически применяет тот же отступ к содержимому исходного файла, который был найден перед оператором
source
(отсутствует, еслиsource
строка не имела отступа, как в вашем примере)