то, что я хочу сделать, это:
1.) Наличие файла конфигурации в качестве шаблона с такими переменными, как $ version $ path (например, конфигурация apache)
2.) Наличие сценария оболочки, который «заполняет» переменные шаблона и записывает сгенерированный файл на диск.
Возможно ли это с помощью сценария оболочки. Я был бы очень благодарен, если бы вы могли назвать некоторые команды / инструменты, которые я могу выполнить, или несколько хороших ссылок.
Это вполне возможно. Очень простой способ реализовать это - сделать файл шаблона сценарием и использовать переменные оболочки, такие как
#! /bin/bash
version="1.2.3"
path="/foo/bar/baz"
cat > /tmp/destfile <<-EOF
here is some config for version $version which should
also reference this path $path
EOF
Вы даже можете сделать это настраиваемым в командной строке, указав version=$1
и path=$2
, так что вы можете запустить его как bash script /foo/bar/baz 1.2.3
. В -
перед тем, как EOF вызовет пробелы перед тем, как строки будут проигнорированы, используйте простой <<EOF
если вы не хотите такого поведения.
Другой способ сделать это - использовать функцию поиска и замены sed.
#! /bin/bash
version="1.2.3"
path="/foo/bar/baz"
sed -e "s/VERSION/$version/g" -e "s/PATH/$path/" /path/to/templatefile > /tmp/destfile
который заменит каждый экземпляр строк VERSION и PATH. Если есть другие причины, по которым эти строки будут в файле шаблона, вы можете выполнить поиск и заменить ВЕРСИЯ или% VERSION%, или что-то с меньшей вероятностью сработает случайно.
Никаких инструментов, кроме /bin/sh
. Учитывая файл шаблона формы
Version: ${version}
Path: ${path}
или даже со смешанным кодом оболочки
Version: ${version}
Path: ${path}
Cost: ${cost}\$
$(i=1; for w in one two three four; do echo Param${i}: ${w}; i=$(expr $i + 1); done)
и файл конфигурации с возможностью синтаксического анализа оболочки, например
version="1.2.3-r42"
path="/some/place/under/the/rainbow/where/files/dance/in/happiness"
cost="42"
это просто расширить до
Version: 1.2.3-r42
Path: /some/place/under/the/rainbow/where/files/dance/in/happiness
Cost: 42$
Param1: one
Param2: two
Param3: three
Param4: four
Действительно, учитывая путь к файлу конфигурации в переменной оболочки config_file
и путь к файлу шаблона в template_file
, все, что вам нужно сделать, это:
. ${config_file}
template="$(cat ${template_file})"
eval "echo \"${template}\""
Возможно, это лучше, чем наличие полного сценария оболочки в качестве файла шаблона (решение @mtinberg).
Полная программа расширения наивных шаблонов:
#!/bin/sh
PROG=$(basename $0)
usage()
{
echo "${PROG} <template-file> [ <config-file> ]"
}
expand()
{
local template="$(cat $1)"
eval "echo \"${template}\""
}
case $# in
1) expand "$1";;
2) . "$2"; expand "$1";;
*) usage; exit 0;;
esac
Это выведет расширение на стандартный вывод; просто перенаправьте стандартный вывод в файл или измените указанное выше очевидным образом, чтобы получить желаемый выходной файл.
Предостережения: Расширение файла шаблона не будет работать, если файл содержит неэкранированные двойные кавычки ("
). По соображениям безопасности нам, вероятно, следует включить некоторые очевидные проверки работоспособности или, что еще лучше, выполнить преобразование экранирования оболочки, если файл шаблона генерируется внешним объектом.
Самый простой способ сделать это просто в Linux CLI - использовать envsubst
и переменные среды.
Пример файла шаблона apache.tmpl
:
<VirtualHost *:${PORT}>
ServerName ${SERVER_NAME}
ServerAlias ${SERVER_ALIAS}
DocumentRoot "${DOCUMENT_ROOT}"
</VirtualHost>
Бегать envsubst
и вывести результат в новый файл my_apache_site.conf
:
export PORT="443"
export SERVER_NAME="example.com"
export SERVER_ALIAS="www.example.com"
export DOCUMENT_ROOT="/var/www/html/"
envsubst < apache.tmpl > my_apache_site.conf
Вывод:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot "/var/www/html/"
</VirtualHost>
Вам, вероятно, следует изучить систему управления конфигурацией, например Кукольный или Повар. Они могут легко сделать то, что вы описали выше, и много Больше.
Если вам нужны легкие и настоящие шаблоны, а не код оболочки, который генерирует новые файлы, обычный выбор: sed
& awk
или perl
. Вот одна ссылка: http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/
Я бы использовал настоящий язык, такой как perl, tcl, python, ruby или что-то еще в этом классе. Что-то созданное для написания сценариев. У всех есть хорошие и простые инструменты для создания шаблонов и масса примеров в Google.
я использую штпл для этого. (мой частный проект, что означает, что он широко не используется. Но, возможно, вы все равно захотите его протестировать)
Например, вы хотите сгенерировать / etc / network / interfaces из csv-файла, вы можете сделать это так:
Содержимое CSV-файла (здесь test.csv):
eth0;10.1.0.10;255.255.0.0;10.1.0.1
eth1;192.168.0.10; 255.255.255.0;192.168.0.1
Шаблон (здесь interfaces.tpl):
#% IFS=';'
#% while read "Val1" "Val2" "Val3" "Val4"; do
auto $Val1
iface $Val1 inet static
address $Val2
netmask $Val3
gateway $Val4
#% done < "$CSVFILE"
Команда:
$ CSVFILE=test.csv sh -c "$( shtpl interfaces.tpl )"
Результат:
auto eth0
iface eth0 inet static
address 10.1.0.10
netmask 255.255.0.0
gateway 10.1.0.1
auto eth1
iface eth1 inet static
address 192.168.0.10
netmask 255.255.255.0
gateway 192.168.0.1
Наслаждайтесь!
Я улучшил ответ FooF, чтобы пользователю не приходилось вручную удалять двойные кавычки:
#!/bin/bash
template="$(cat $1)"
template=$(sed 's/\([^\\]\)"/\1\\"/g; s/^"/\\"/g' <<< "$template")
eval "echo \"${template}\""
Недавно я опубликовал bash-скрипт, который выполняет именно это, используя синтаксис шаблона, подобный jinja. Это называется печенье. Вот демо:
Чтобы расширить отличный ответ @ FooF (новые строки не форматировались в комментариях), используя символы управления heredoc +, вы можете разрешить произвольные символы и имена файлов:
template() {
# if [ "$#" -eq 0 ] ; then return; fi # or just error
eval "cat <<$(printf '\x04\x04\x04');
$(cat $1)
"
}
Это принимает любой ненулевой символ и обрезает только раньше, если 3 ^D
байты встречаются в отдельной строке (реально никогда). zsh поддерживает даже нулевые терминаторы, поэтому printf '\x00\x00\x00'
должно сработать. template
работает даже с коварными именами файлов, например:
for num in `seq 10`; do
template 'foo "$ .html' # works
done
Будьте осторожны, шаблоны оболочки могут «расширять» произвольные команды, например $(launch_nukes.sh --target $(curl -sL https://freegeoip.app/csv/ | cut -d, -f 9,10))
. С большой силой…
Изменить: если вы действительно не хотите, чтобы ваши файлы запускали на вас ядерное оружие, просто sudo -u nobody sh
(или другого безопасного пользователя) заранее.
Я, наверное, опоздал на эту вечеринку. Однако я наткнулся на ту же проблему и решил создать свой собственный шаблонизатор BASH в несколько строк кода:
Допустим, у вас есть это file.template
:
# My template
## Author
- @NAME@ <@EMAIL@>
И это rules
файл:
NAME=LEOPOLDO WINSTON
EMAIL=leothewinston\@leoserver.com
Вы выполняете эту команду:
templater rules < file.template
Вы получите это:
# My template
## Author
- LEOPOLDO WINSTON <leothewinston@leoserver.com>
Вы можете установить его:
bpkg install vicentebolea/bash-templater
Это проект сайт
Возможно, мне удастся пробудить ваш интерес к сценарию выше всех других сценариев, которые до сих пор предлагались здесь.
Учитывая template.txt:
Hello, {{person}}!
Пожалуйста, выполните:
$ person=Bob ./render template.txt
И вы увидите результат
Hello, Bob!
Вы можете записать его в файл, перенаправив stdout следующим образом:
$ person=Bob ./render template.txt > rendered.txt
Или объявите свои переменные в файле, а затем создайте его. Лучше всего это делать внутри скрипта:
#!/usr/bin/env bash
source ./myvalues
./render template.txt > rendered.txt
Преимущество этого средства визуализации перед всеми другими заключается в том, что он не расширяет никакие переменные, такие как $foo
или ${bar}
что весьма полезно, если то, что вы пытаетесь визуализировать, само по себе является сценарием! Кроме того, указанный модуль визуализации прошел модульное тестирование и получил запросы на вытягивание от сообщества.
Мне сказали, что я должен заявить, что написал этот сценарий сам. Таким образом, я отмечу, что я написал его и доступен в GitHub по адресу https://github.com/relaxdiego/renderest
Некоторая статистика скрипта, если вас это интересует:
-------------------------
| Effective LOCs | 20 |
| Test Coverage | 100% |
| Test LOCs | 50 |
-------------------------