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

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


当前回答

下面是一种让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是指定的环境变量。

其他回答

下面是一种让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是指定的环境变量。

Sed!

鉴于template.txt:

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

我们只能说:

sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt

感谢Jonathan Leffler提供的将多个-e参数传递给同一个sed调用的技巧。

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

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

我创建了一个名为shtpl的shell模板脚本。我的shtpl使用类似jinja的语法,现在我使用ansible很多,我很熟悉:

$ cat /tmp/test
{{ aux=4 }}
{{ myarray=( a b c d ) }}
{{ A_RANDOM=$RANDOM }}
$A_RANDOM
{% if $(( $A_RANDOM%2 )) == 0 %}
$A_RANDOM is even
{% else %}
$A_RANDOM is odd
{% endif %}
{% if $(( $A_RANDOM%2 )) == 0 %}
{% for n in 1 2 3 $aux %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/passwd field #$n: $(grep $USER /etc/passwd | cut -d: -f$n)
{% endfor %}
{% else %}
{% for n in {1..4} %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/group field #$n: $(grep ^$USER /etc/group | cut -d: -f$n)
{% endfor %}
{% endif %}


$ ./shtpl < /tmp/test
6535
6535 is odd
$myarray[0]: a
/etc/group field #1: myusername
$myarray[1]: b
/etc/group field #2: x
$myarray[2]: c
/etc/group field #3: 1001
$myarray[3]: d
/etc/group field #4: 

更多信息在我的github

对我来说,这是最简单和最强大的解决方案,你甚至可以使用相同的命令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 :)