在单个传递中填充文件中的占位符

时间:2009-01-02 16:11:42

标签: bash replace sed awk textutils

我有一个带占位符字符串的骨架文本文件:

blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$

等等。占位符的特定“形式”并不重要 - 我可以将它们更改为最适合特定实现的任何内容。

我有一个bash脚本,我知道占位符的值,我需要生成一个新文件,占位符替换为值。

#! /bin/sh
PLACEHOLDER_1 = 'string 1'
PLACEHOLDER_2 = 'multiline 
string 
2'
# TODO: Generate file output.txt from file output.template 
#       using placeholders above.

我可以用sed多次通过,但这并不好玩。我想要使用Perl。我想只使用textutils和bash。

一次通过我想要的最佳方式是什么?

5 个答案:

答案 0 :(得分:10)

这是一种没有sed的方法:

首先,稍微修改一下模板文件,其中占位符是bash变量:

blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2

脚本:

#! /bin/sh
templatefile=output.template
outputfile=output.txt

PLACEHOLDER_1='string 1'

PLACEHOLDER_2='multiline 
string 
2'

# DONE: Generate file output.txt from file output.template 
#       using placeholders above.

echo "$(eval "echo \"$(cat $templatefile)\"")" > $outputfile

这是一个演示脚本中包含的模板的版本,但有一个扭曲。它还演示了默认值,也可以在模板文件版本中使用,还可以在模板中进行数学运算:

#! /bin/sh
template='blah blah blah
blah $PLACEHOLDER_1
blah
${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some
lines
of
text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'
# default operands to zero (or 1) to prevent errors due to unset variables
outputfile=output.txt

# gears spin, bells ding, values for placeholders are computed

PLACEHOLDER_1='string 1'

PLACEHOLDER_2='multiline 
string 
2'

VAL_1=2

VAL_2=4

unset PLACEHOLDER_3 # so we can trigger one of the defaults

# Generate file output.txt from variable $template 
#       using placeholders above.

echo "$(eval "echo \"$template\"")" > $outputfile

没有sed,没有循环,只是毛茸茸的嵌套和引号。我很确定所有引用都会保护你免受模板文件中的恶意攻击,但我不会保证它。

答案 1 :(得分:9)

你仍然可以使用sed在一次传递中进行替换。您只需在一个命令中指定所有替换。

例如

sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>

答案 2 :(得分:5)

在上一个答案的基础上,也许使用数组并计算sed字符串?

#!/bin/sh
PLACEHOLDER[0]='string 1'
PLACEHOLDER[1]='multiline 
string 
2'

s="sed -i "
for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do 
    echo ${PLACEHOLDER[$i]}
    s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;"
done
echo $s

然而,似乎在多行字符串上失败了。

我不知道Bash阵列可能是多么便携。以上片段用“GNU bash,版本3.2.17(1)-release(i386-apple-darwin9.0)”测试

答案 3 :(得分:2)

我的bash唯一解决方案:

TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""

答案 4 :(得分:1)

我只是偶然发现了这个问题,因为我只是在寻找相同的问题,我找到了envsubst(1)

如果您不介意使用环境变量,可以使用 envsubst

PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
string 
2' envsubst < output.template 

如果你有很多变量,你可以将它们存储在一个文件中,而只是source它(记得在源文件的末尾使用export!)