假设我有一个像这样的 shell 配置文件config
:
HOST=localhost
PORT=8080
template
现在我有一个这样的模板:
The host is <%= @HOST %>
The port is <%= @PORT %>
如何用文件template
中的值替换占位符?config
我当然可以这样做:
$ . config
$ sed -e "s/<%= @HOST %>/$HOST/" \
> -e "s/<%= @PORT %>/$PORT/" < template
The host is localhost
The port is 8080
但如果有很多配置值,这就变得太麻烦了。我将如何以更通用的方式做到这一点?我想迭代每个占位符并用实际值替换它。
答案1
你可以这样做:
eval "cat << __end_of_template__
$(sed 's/[\$`]/\\&/g;s/<%= @\([^ ]*\) %>/${\1}/g' < template)
__end_of_template__"
也就是说,让 sed在转义所有,和字符后替换所有<%= @xxx %>
的,并让 shell 进行扩展。${xxx}
$
\
`
或者,如果您不能保证其中template
不包含一行__end_of_template__
:
eval "cut -c2- << x
$(sed 's/[\$`]/\\&/g;s/<%= @\([^ ]*\) %>/${\1}/g;s/^/y/' < template)
x"
答案2
一个awk
办法:
awk -F= 'FNR==NR{v[$1]=$2;next};{for(p in v)gsub("<%= @"p" %>",v[p])};1' config template
更新根据斯蒂芬·查泽拉斯的评论允许值中包含“=”符号:
awk -F= 'FNR==NR{v[$1]=substr($0,length($1)+2);next};{for(p in v)gsub("<%= @"p" %>",v[p])};1' config template
答案3
您可以使用小胡子(1)替换一堆模板变量:
$ { echo ---; sed 's/=/: /' config; echo --- } \
| mustache - <(sed -e 's/<%= @/{{/g' -e 's/%>/}}/g' template)
管道的第一个元素将您的配置分配转换为我的小胡子可以理解的 YAML 语法。第二个sed
命令将<%= @VAR %>
样式变量引用替换为小胡子{{ VAR }}
变量引用。
在 Fedora 上,mustache
是软件包的一部分rubygem-mustache
。
或者,您可以使用envsubst
(由包提供gettext
),例如:
$ ( export $(cat config) ; sed -e 's/<%= @\([^%]*\) %>/${\1}/g' template
| envsubst )
要求您的变量分配在 shell 中也有效。
答案4
单程:
#!/bin/sh
. config
while read line
do
eval echo $(echo $line | sed "s/\([^<]*\)<%= @\([^ ]*\) %>/\1 \$\2/")
done < template
结果:
The host is localhost
The port is 8080
使用sed
,我们提取直到“<”的字符并形成一个组(\1
),并提取占位符并形成另一个组(\2
)。将其替换为第一组,然后用美元符号替换第二组。只需使用该eval
命令,就可以计算变量并对其进行扩展。