6

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

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 本身。

一次性完成我想做的事情的最佳方法是什么?

4

5 回答 5

11

这是一种不使用 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,没有循环,只有毛茸茸的嵌套和引号。我很确定所有引用都会保护您免受模板文件中的恶意内容的侵害,但我不保证这一点。

于 2009-05-29T05:37:55.867 回答
9

您仍然可以使用 sed 一次性完成替换。您只需要在一个命令中指定所有替换。

例如。

sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>
于 2009-01-02T16:22:14.610 回答
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)”测试

于 2009-01-02T17:28:15.600 回答
2

我的 bash 唯一解决方案:

TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""
于 2010-10-26T15:51:53.450 回答
1

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

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

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

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

于 2015-03-31T20:54:37.603 回答