我想要实现的目标是:
有一个配置文件作为模板,带有 $version $path 等变量(例如 apache 配置)
有一个 shell 脚本“填充”模板的变量并将生成的文件写入磁盘。
使用 shell 脚本可以实现这一点吗?如果您能说出一些可以实现这一点的命令/工具或一些好的链接,我将不胜感激。
答案1
这是非常有可能的。实现这一点的一个非常简单的方法是将模板文件实际作为脚本并使用 shell 变量,例如
#! /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
如果您不想要这种行为,请使用 plain。
另一种方法是使用 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% 或一些不太可能意外触发的内容。
答案2
在 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>
答案3
除了 之外不需要其他工具/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
这会将扩展输出到标准输出;只需将标准输出重定向到文件或以明显的方式修改上述内容以生成所需的输出文件。
注意事项:如果文件包含未转义的双引号 ( ),则模板文件扩展将不起作用"
。出于安全原因,我们可能应该包含一些明显的健全性检查,或者更好的是,如果模板文件是由外部实体生成的,则执行 shell 转义转换。