替换模板文件中的bash变量 [英] Replace bash variables in template file
问题描述
我试图使用Bash来运行某种形式的安装过程.在此过程中,将复制配置文件,并在其中替换某些值.这样的配置可以在下面找到:
I am attempting to use Bash in order to run a form of an install process. During this process, a configuration file is copied and certain values are replaced inside of it. Such a config can be found below:
server {
listen 80;
root ${INSTALLPATH};
server_name ${SITEURL};
client_max_body_size 20m;
client_body_timeout 120s;
location / {
try_files /public/router.php =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_pass ${PHPSERV};
fastcgi_index router.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location /assets {
try_files /app/$uri =404;
}
}
#Enables HTTPS access
#This requires you to install certificates and is not enabled by default
#If you wish to enable HTTPS, uncomment (remove the #s) from the below lines
#And change the ssl_certificate and ssl_certificate_key to point to the correct
#certificates.
#server {
# listen 443;
# root ${INSTALLPATH};
# server_name ${SITEURL};
#
# ssl on;
# ssl_certificate /etc/nginx/ssl/site.crt;
# ssl_certificate_key /etc/nginx/ssl/site.key;
#
# location / {
# try_files /public/router.php =404;
# fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# fastcgi_pass ${PHPSERV};
# fastcgi_index router.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include /etc/nginx/fastcgi_params;
# }
#
# location /assets {
# try_files /app/$uri =404;
# }
#
#}
我发现大多数示例都源自eval的使用,并且我尝试使用eval进行此替换,但是似乎这里的文件没有正确扩展,bash尝试执行一些操作并且可以t.
I have been finding that most examples stem off the use of eval, and I have tried using that to do this replacement, however it appears that the file here does not properly expand, and bash tries to execute some stuff and can't.
目前,我有这个
INSTALLPATH="/var/www/html/mycustomsite/"
PHPSERV="127.0.0.1:9000"
SITEURL="example.com"
while read -r line; do
eval echo -e "${line}"
done < template
但是,这不能正确替换声明的值,也不能正确生成文件.例如,它会丢失以#开头的任何行并尝试执行其他行(以及丢失一些空格).
However, this does not properly replace the values that are declared, nor does it generate the file correctly. It loses for example any line that starts with # and tries to execute others (along with losing some spacing).
仅使用大多数Linux系统上可用的Bash和命令来执行此操作的正确方法是什么?
What would be the correct way to do this, using just Bash and commands available on most Linux systems?
推荐答案
安全提示
这不会解决安全问题!使用eval
是邪恶!
兼容的答案并不更好!
当然,您必须对模板的内容充满信心!
Of course, you have to be confident about the content of your template!!
否则,请尝试使用 sed 的问题! (请参阅我的最后答案)
If else, try using sed! (see my last answer)
在 bash 的问题,您可以简单地:>
Under bash you can simply:
eval "INSTALLPATH='/somepath/somewhere' SITEURL='example.com' PHPSERV='127.0.0.1:9000'; echo \"$(<template)\""
或
eval "INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
echo \"$(<template)\""
使用eval
时,可以将生成的配置文件存储到一个变量中:
As you're using eval
, you could store your resulting config file into one variable:
eval "INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
cfgBody=\"$(<template)\""
然后
echo "$cfgBody"
和/或
echo "$cfgBody" >/cfgpath/cfgfile
将其循环执行
tmplBody="$(<template)"
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
[ "$CFGFILE" ] && eval "echo \"$tmplBody\"" >"$CFGFILE"
done <<<"
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
"
注意:在第二行上,有转义的空格(以反斜杠\
和引号'
开头. strong>反斜杠告诉read
不要拆分变量,并且必须将引号添加到结果/tmp/file2
中.
Note: On second line, there are escaped spaces (prepanded with a backshash \
and quotes '
. The backslash tell read
to not split the variable, and the quotes have to be added into the resulting /tmp/file2
.
在 posix的问题
Under posix shell, you may do this way:
#!/bin/sh
(
cat <<eohead
#!/bin/sh
INSTALLPATH='/somepath/somewhere'
SITEURL='example.com'
PHPSERV='127.0.0.1:9000';
cat <<eof
eohead
cat template
echo eof
) | /bin/sh
这不需要bash,已通过 dash 和 busybox 的问题.
This don't require bash, was tested under dash and busybox.
sedcmd=''
for var in INSTALLPATH SITEURL PHPSERV;do
printf -v sc 's/${%s}/%s/;' $var "${!var//\//\\/}"
sedcmd+="$sc"
done
sed -e "$sedcmd" <template
可能会陷入循环:
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
if [ "$CFGFILE" ] ;then
sedcmd=''
for var in INSTALLPATH SITEURL PHPSERV;do
printf -v sc 's/${%s}/%s/;' $var "${!var//\//\\/}"
sedcmd+="$sc"
done
sed -e "$sedcmd" <template >"$CFGFILE"
fi
done <<<"
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
"
兼容的答案,使用sed
这可以在没有所谓的 bashisms 进入循环的情况下起作用:
Compatible answer, using sed
This could work without so called bashisms, into a loop:
#!/bin/sh
while read INSTALLPATH SITEURL PHPSERV CFGFILE;do
sedcmd="s|\\\${INSTALLPATH}|${INSTALLPATH}|;"
sedcmd="${sedcmd}s|\\\${SITEURL}|${SITEURL}|;"
sedcmd="${sedcmd}s|\\\${PHPSERV}|${PHPSERV}|;"
sed -e "$sedcmd" template >"$CFGFILE"
done <<eof
/somepath/somewhere example.com 127.0.0.1:9000 /tmp/file1
'/some\ other\ path/elsewhere' sample2.com 127.0.0.1:9001 /tmp/file2
eof
比较输出:
diff -u99 /tmp/file{1,2}
--- /tmp/file1 2015-05-31 11:02:03.407463963 +0200
+++ /tmp/file2 2015-05-31 11:02:03.407463963 +0200
@@ -1,22 +1,22 @@
server {
listen 80;
- root /somepath/somewhere;
- server_name example.com;
+ root '/some other path/elsewhere';
+ server_name sample2.com;
client_max_body_size 20m;
client_body_timeout 120s;
location / {
try_files /public/router.php =404;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
- fastcgi_pass 127.0.0.1:9000;
+ fastcgi_pass 127.0.0.1:9001;
fastcgi_index router.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location /assets {
try_files /app/$uri =404;
}
}
这篇关于替换模板文件中的bash变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!