替换模板文件中的bash变量

时间:2015-05-29 22:04:50

标签: linux bash

我正在尝试使用Bash来运行一种安装过程。在此过程中,将复制配置文件,并在其中替换某些值。这样的配置可以在下面找到:

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,我尝试使用它来替换它,但是看起来这里的文件没有正确扩展,而bash试图执行一些东西而且可以'吨。

目前,我有这个

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

但是,这不能正确替换声明的值,也不能正确生成文件。例如,任何以#开头并尝试执行其他行的行(以及丢失一些间距)都会丢失。

使用大多数Linux系统上提供的Bash和命令,这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:4)

安全提示

这不会解决安全问题!使用eval evil

兼容的答案并不是更好!

当然,您必须对模板的内容充满信心!!

如果不是,请尝试使用! (见我的上一个答案)

仅限快速方式!:

下,您可以简单地:

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时,您可以将生成的配置文件存储到一个变量中:

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
"

注意:在第二行,有转义空格(预先填充了反馈\ 引号{{1} 。反斜杠告诉'不要拆分变量,并且必须将引号添加到生成的read中。

软路(兼容的答案)

下,您可以这样做:

/tmp/file2

这不需要bash,在下进行了测试。

没有 eval

#!/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

可以进入循环:

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 "

的兼容答案

这可以在没有所谓的 bashisms 的情况下工作到循环中:

sed

比较输出:

#!/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