Я пишу сценарий для автоматизации создания файлов конфигурации для Apache и PHP для моего собственного веб-сервера. Я не хочу использовать графические интерфейсы вроде CPanel или ISPConfig.
У меня есть несколько шаблонов файлов конфигурации Apache и PHP. Скрипту Bash необходимо читать шаблоны, производить подстановку переменных и выводить проанализированные шаблоны в какую-то папку. Каков наилучший способ сделать это? Я могу придумать несколько способов. Какой из них лучший или, может быть, есть еще способы сделать это лучше? Я хочу сделать это в чистом Bash (например, в PHP это просто)
1) Как заменить заполнители $ {} в текстовом файле?
template.txt:
the number is ${i}
the word is ${word}
script.sh:
#!/bin/sh
#set variables
i=1
word="dog"
#read in template one line at the time, and replace variables
#(more natural (and efficient) way, thanks to Jonathan Leffler)
while read line
do
eval echo "$line"
done < "./template.txt"
Кстати, как мне перенаправить вывод во внешний файл здесь? Нужно ли мне что-то экранировать, если переменные содержат, скажем, кавычки?
2) Использование cat & sed для замены каждой переменной ее значением:
Данный template.txt:
The number is ${i}
The word is ${word}
Команда:
cat template.txt | sed -e "s/\${i}/1/" | sed -e "s/\${word}/dog/"
Мне это кажется плохим из-за необходимости избегать множества разных символов и со многими переменными строка будет слишком длинной.
Вы можете придумать какое-нибудь другое элегантное и безопасное решение?
источник
Ответы:
Вы можете использовать это:
для замены всех
${...}
строк соответствующими переменными окружения (не забудьте экспортировать их перед запуском этого скрипта).Для чистого bash это должно работать (при условии, что переменные не содержат строк $ {...}):
, Решение, которое не зависает, если RHS ссылается на некоторую переменную, которая ссылается на себя:
ВНИМАНИЕ : я не знаю, как правильно обрабатывать ввод с помощью NUL в bash или сохранять количество завершающих символов новой строки. Последний вариант представлен как есть, потому что оболочки «любят» двоичный ввод:
read
интерпретирует обратную косую черту.read -r
не интерпретирует обратную косую черту, но все равно отбрасывает последнюю строку, если она не заканчивается новой строкой."$(…)"
будет полоса , как много хвостовых символов новой строки , как там присутствует, так что в конечном…
с; echo -n a
и использованиемecho -n "${line:0:-1}"
: это капли последнего символа (которыйa
) и сохраняют как много хвостовых символов новой строки , поскольку не было на входе ( в том числе нет).источник
[^}]
на[A-Za-Z_][A-Za-z0-9_]
в версии bash, чтобы оболочка не выходила за рамки строгой подстановки (например, если она пыталась обработать${some_unused_var-$(rm -rf $HOME)}
).$&
решение perl на""
: сначала оставляет${...}
нетронутым, если он не удается заменить, второй заменяет его пустой строкой.while
цикл считывал последнюю строку, даже если она не заканчивается символом новой строки, используйтеwhile read -r line || [[ -n $line ]]; do
. Кроме того, вашаread
команда удаляет начальные и конечные пробелы из каждой строки; чтобы избежать этого, используйтеwhile IFS= read -r line || [[ -n $line ]]; do
\
-эскапирования).Пытаться
envsubst
источник
envsubst
не требуется при использовании heredoc, поскольку bash рассматривает heredoc как буквальную строку с двойными кавычками и уже интерполирует в нее переменные. Однако это отличный выбор, если вы хотите прочитать шаблон из другого файла. Хорошая замена гораздо более громоздкомуm4
.envsubst
это утилита GNU gettext, и на самом деле она не так уж и надежна (поскольку gettext предназначена для локализации человеческих сообщений). Что наиболее важно, он не распознает замену $ {VAR} с экранированной обратной косой чертой (поэтому у вас не может быть шаблона, который использует замены $ VAR во время выполнения, например, сценарий оболочки или файл conf Nginx). См. Мой ответ о решении, которое обрабатывает экранирование обратной косой черты.<<"EOF"
, который не интерполирует переменные (терминаторы в кавычках похожи на одинарные кавычки в heredocs).cat template.txt | envsubst
envsubst был для меня новым. Фантастика.
Для записи, использование heredoc - отличный способ создать шаблон для файла conf.
источник
envsubst
потому, что это спасло меня отapt-get install gettext-base
лишнего в моем DockerfileЯ согласен с использованием sed: это лучший инструмент для поиска / замены. Вот мой подход:
источник
-i
опция (редактировать файлы на месте), аналогичная опции perl . Проверьте страницу руководства для вашего sed .Я думаю, что eval работает очень хорошо. Он обрабатывает шаблоны с переносами строк, пробелами и всевозможными вещами bash. Если, конечно, вы полностью контролируете сами шаблоны:
Разумеется, этот метод следует использовать с осторожностью, поскольку eval может выполнять произвольный код. Запустить это как root практически не может быть и речи. Цитаты в шаблоне нужно экранировать, иначе они будут съедены
eval
.Вы можете также использовать здесь документы , если вы предпочитаете ,
cat
чтобыecho
@plockc предоставил решение, которое позволяет избежать проблемы с экранированием цитаты bash:
Изменить: удалена часть о запуске этого как root с помощью sudo ...
Изменить: добавлен комментарий о том, как нужно экранировать кавычки, добавлено решение plockc в микс!
источник
eval
edecho
/cat
обрабатывают их; попробуйeval "echo \"'\$HOME'\""
.У меня есть решение bash, такое как mogsie, но с heredoc вместо herestring, чтобы вы могли избежать двойных кавычек
источник
${param:?}
вложенным текстом вокруг необязательных параметров. Пример:${DELAY:+<delay>$DELAY</delay>}
заменяется на ничто, если DELAY не определено, и <delay> 17 </delay>, когда DELAY = 17._EOF_$$
.$trailing_newline
, или использовать$NL5
и убедиться, что она расширяется до 5 символов новой строки.template.txt
будет работать, чтобы сохранить завершающие символы новой строки.eval
, если онtemplate.txt
содержитсяEOF
в отдельной строке, он преждевременно завершит работу с файлом here-doc и, таким образом, прервет команду. (Совет от @xebeche).Редактировать 6 января, 2017
Мне нужно было сохранить двойные кавычки в моем файле конфигурации, поэтому помогает двойное экранирование двойных кавычек с помощью sed:
Я не могу думать о сохранении новых строк в конце, но пустые строки между ними сохраняются.
Хотя это старая тема, ИМО я нашел здесь более элегантное решение: http://pempek.net/articles/2013/07/08/bash-sh-as-template-engine/
Все кредиты Грегори Пакошу .
источник
eval "echo \"$(sed 's/\"/\\"/g' $1)\""
$variables
).Вместо того, чтобы изобретать колесо, используйте envsubst. Может использоваться практически в любом сценарии, например, для создания файлов конфигурации из переменных среды в контейнерах докеров.
Если на Mac убедитесь, что у вас есть homebrew, свяжите его с помощью gettext:
./template.cfg
./.env:
./configure.sh
Теперь просто используйте это:
источник
envsubst
действительно работает.envsubst
не работает на MacOS, вам необходимо установить его с помощью доморощенного:brew install gettext
.Более длинная, но более надежная версия принятого ответа:
Это расширяет все экземпляры
$VAR
или${VAR}
до их значений среды (или, если они не определены, до пустой строки).Он правильно экранирует обратную косую черту и принимает экранированный обратной косой чертой знак $, чтобы запретить подстановку (в отличие от envsubst, которая, как оказалось, этого не делает ).
Итак, если ваша среда:
и ваш шаблон:
результат будет:
Если вы хотите избежать обратной косой черты только перед символом $ (вы можете написать "C: \ Windows \ System32" в шаблоне без изменений), используйте эту слегка измененную версию:
источник
Я бы сделал это таким образом, вероятно, менее эффективным, но более легким для чтения / обслуживания.
источник
sed -e 's/VARONE/NEWVALA/g' -e 's/VARTWO/NEWVALB/g' -e 's/VARTHR/NEWVALC/g' < $TEMPLATE > $OUTPUT
Если вы хотите использовать шаблоны Jinja2 , см. Этот проект: j2cli .
Поддерживает:
источник
Принимая ответ от ZyX с использованием чистого bash, но с сопоставлением регулярных выражений нового стиля и косвенной заменой параметров, он становится:
источник
Если использование Perl - вариант, и вы довольны основанием расширений только на переменных среды (в отличие от всех переменных оболочки ), рассмотрите надежный ответ Стюарта П. Бентли .
Этот ответ направлен на предоставление решения только для bash, которое, несмотря на его использование,
eval
должно быть безопасным в использовании .Эти цели являются:
${name}
и$name
переменные.$(...)
и унаследованный синтаксис`...`
)$((...))
и унаследованный синтаксис$[...]
).\
(\${name}
)."
и\
экземпляры.Функция
expandVars()
:Примеры:
${HOME:0:10}
, если они не содержат встроенных команд или арифметических подстановок, таких как${HOME:0:$(echo 10)}
$(
и`
экземпляры слепо экранирование).${HOME
(отсутствие закрытия}
) BREAK функции.\$name
предотвращает расширение.\
за которым не следует,$
сохраняется как есть.\
экземпляров, вы должны удвоить их ; например:\\
->\
- так же, как просто\
\\\\
->\\
0x1
,0x2
,0x3
.eval
.Если вы ищете более ограниченное решение, которое поддерживает только
${name}
расширения, то есть с обязательными фигурными скобками, игнорируя$name
ссылки, см. Этот мой ответ .Вот улучшенная версия
eval
бесплатного решения только для bash из принятого ответа :Усовершенствования:
${name}
и$name
переменных.\
-экранирование ссылок на переменные, которые не следует расширять.eval
решения на основе выше,источник
Вот еще одно чистое решение bash:
$ cat code
$ cat template
(с завершающими символами новой строки и двойными кавычками)вывод
источник
Вот еще одно решение: сгенерируйте сценарий bash со всеми переменными и содержимым файла шаблона, этот сценарий будет выглядеть так:
Если мы загрузим этот скрипт в bash, он выдаст желаемый результат:
Вот как сгенерировать этот сценарий и передать его в bash:
обсуждение
cat
команду с HEREDOCЕсли вы хотите перенаправить этот вывод в файл, замените последнюю строку на:
источник
Эта страница описывает ответ с awk
источник
Прекрасный чехол для штпл . (мой проект, поэтому он не так широко используется и не имеет документации. Но вот решение, которое он предлагает. Можете ли вы его протестировать.)
Просто выполните:
Результат:
Радоваться, веселиться.
источник
Это чистая функция bash, настраиваемая по вашему вкусу, используемая в продакшене и не должна прерываться при вводе. Если сломается - дайте знать.
источник
Вы также можете использовать bashible (который внутренне использует метод оценки, описанный выше / ниже).
Вот пример того, как сгенерировать HTML из нескольких частей:
https://github.com/mig1984/bashible/tree/master/examples/templates
источник
Вот функция bash, которая сохраняет пробелы:
источник
Вот модифицированный
perl
сценарий, основанный на нескольких других ответах:Возможности (в зависимости от моих потребностей, но должны быть легко изменены):
источник
Посмотрите на скрипт Python для простой замены переменных здесь: https://github.com/jeckep/vsubst
Использовать очень просто:
источник
Чтобы продолжить ответ plockc на этой странице, вот версия, подходящая для тире, для тех из вас, кто хочет избежать башизмов.
источник
Нет ничего проще, чем:
$ person = Bob ./render template.txt> rendered.txt
См. Https://github.com/relaxdiego/renderest
источник