Answers:
这是很有可能的。一种简单的实现方法是将模板文件实际用作脚本并使用诸如
#! /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
and 来使其在命令行上可配置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或%VERSION%或不太可能被意外触发的字符串。
除了,没有其他必要的工具/bin/sh
。给定形式的模板文件
Version: ${version}
Path: ${path}
甚至包括混合的shell代码
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)
和一个shell可解析的配置文件,例如
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
实际上,在shell变量中给出了配置文件config_file
的路径,在中给出了模板文件的路径template_file
,您所需要做的就是:
. ${config_file}
template="$(cat ${template_file})"
eval "echo \"${template}\""
这可能比将完整的Shell脚本作为模板文件(@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>
name
,<%= name %>
模板中的字符串将被替换为name
的值。name
显然,两个系统之间在模板外部进行定义的方式有所不同。
如果您想要轻量级且真实的模板,而不是生成新文件的shell代码,通常的选择是sed
&awk
或perl
。这是一个链接:http : //savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/
我,我会在该类中使用像perl,tcl,python,ruby之类的真实语言。为脚本编写的东西。他们都有很好的,简单的模板工具以及Google中的大量示例。
我为此使用shtpl。(我的私人项目,这意味着它并未得到广泛使用。但是也许您还是想对其进行测试)
例如,您要从一个csv文件生成一个/ etc / network / interfaces,您可以这样做:
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
请享用!
我最近发布了一个bash脚本,该脚本使用类似于jinja的模板语法来完成该任务。它称为cookie。这是一个演示:
我可能参加这个聚会很晚。但是,我偶然发现了同样的问题,我选择了用几行代码创建自己的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
这是项目现场
要扩展@FooF的好答案(换行符未在注释中格式化),请使用heredoc +控制字符,您可以允许任意字符和文件名:
template() {
# if [ "$#" -eq 0 ] ; then return; fi # or just error
eval "cat <<$(printf '\x04\x04\x04');
$(cat $1)
"
}
这接受任何非空字符,并且仅^D
在其自己的行上遇到3 个字节时才截断(实际上从不)。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
事先(或其他安全用户)使用。