我想将一个“模板”文件的输出管道到MySQL中,该文件具有像${dbName}这样的变量。替换这些实例并将输出转储到标准输出的命令行实用程序是什么?

输入文件被认为是安全的,但是可能存在错误的替换定义。执行替换应避免执行意外的代码执行。


当前回答

这里有很多选择,但我想把我的扔到堆里。它是基于perl的,只针对形式为${…},将要处理的文件作为参数,并在stdout上输出转换后的文件:

use Env;
Env::import();

while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }

print "$text";

当然,我不是一个真正的perl人,所以很容易有一个致命的缺陷(对我来说是如此)。

其他回答

我在想同样的事情时发现了这条线索。这启发了我(注意反节拍)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world

更新

下面是yottatsa关于类似问题的解决方案,它只替换像$VAR或${VAR}这样的变量,并且是一个简短的一行程序

i=32 word=foo envsubst < template.txt

当然,如果i和word在你的环境中,那么它只是

envsubst < template.txt

在我的Mac上,它看起来是作为gettext和MacGPG2的一部分安装的

旧的答案

这里是一个改进的解决方案从mogsie对类似的问题,我的解决方案不需要你的双引号,mogsie的做,但他是一个一行!

eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null

这两种解决方案的强大之处在于,您只能获得几种正常情况下不会发生的shell扩展类型$((…)),'…',和$(…),虽然反斜杠在这里是一个转义字符,但您不必担心解析有bug,它可以很好地处理多行。

下面是一种让shell为您执行替换的方法,就像在双引号之间输入文件的内容一样。

以包含内容的template.txt为例:

The number is ${i}
The word is ${word}

下面的代码行将使shell插入template.txt的内容并将结果写入标准输出。

i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'

解释:

I和word作为环境变量传递给sh的执行。 Sh执行传入的字符串的内容。 相邻的字符串变成一个字符串,这个字符串就是: “echo”+“$(cat template.txt)”+ " ' 由于替换在"之间,"$(cat template.txt)"成为cat template.txt的输出。 因此sh -c执行的命令变成: echo“数字是${i}\n字是${word}”, 其中I和word是指定的环境变量。

对我来说,这是最简单和最强大的解决方案,你甚至可以使用相同的命令eval echo "$(<template.txt)包含其他模板:

带有嵌套模板的示例

创建模板文件,变量是常规bash语法${VARIABLE_NAME}或$VARIABLE_NAME

你必须在模板中用\转义特殊字符,否则它们将被eval解释。

template.txt

Hello ${name}!
eval echo $(<nested-template.txt)

nested-template.txt

Nice to have you here ${name} :\)

创建源文件

template.source

declare name=royman 

解析模板

source template.source && eval echo "$(<template.txt)"

输出

Hello royman!
Nice to have you here royman :)

file.tpl:

The following bash function should only replace ${var1} syntax and ignore 
other shell special chars such as `backticks` or $var2 or "double quotes". 
If I have missed anything - let me know.

script.sh:

template(){
    # usage: template file.tpl
    while read -r line ; do
            line=${line//\"/\\\"}
            line=${line//\`/\\\`}
            line=${line//\$/\\\$}
            line=${line//\\\${/\${}
            eval "echo \"$line\""; 
    done < ${1}
}

var1="*replaced*"
var2="*not replaced*"

template file.tpl > result.txt