bash 一次性填充文件中的占位符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/407279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fill placeholders in file in single pass
提问by Alexander Gladysh
I have a skeleton text file with placeholder strings:
我有一个带有占位符字符串的骨架文本文件:
blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$
and so on. Specific "form" of placeholders does not matter -- I may change them to whatever most comfortable for specific implementation.
等等。占位符的特定“形式”无关紧要——我可以将它们更改为最适合特定实现的任何形式。
I have a bash script where I know values for placeholders, and I need to generate a new file, with placeholders replaced with values.
我有一个 bash 脚本,我知道占位符的值,我需要生成一个新文件,用值替换占位符。
#! /bin/sh
PLACEHOLDER_1 = 'string 1'
PLACEHOLDER_2 = 'multiline
string
2'
# TODO: Generate file output.txt from file output.template
# using placeholders above.
I may do this in multiple passes with sed, but it is not fun. I do notwant to use Perl. I want to use textutils and bash itself only.
我可以使用 sed 多次执行此操作,但这并不有趣。我不希望使用Perl。我只想使用 textutils 和 bash 本身。
What is the best way to do what I want in a single pass?
在单次通过中做我想做的最好的方法是什么?
回答by Paused until further notice.
Here's a way to do it without sed:
这是一种无需 sed 的方法:
First, a slightly modified template file in which the placeholders are bash variables:
首先,一个稍微修改的模板文件,其中占位符是 bash 变量:
blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2
And the script:
和脚本:
#! /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
Here's a version that demonstrates a template contained within the script, but with a twist. It also demonstrates default values, which can also be used in the template file version, plus you can do math in the template:
这是一个演示包含在脚本中的模板的版本,但有所不同。它还演示了默认值,也可以在模板文件版本中使用,此外您可以在模板中进行数学运算:
#! /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
No sed, no loops, just hairy nesting and quotes. I'm pretty sure all the quoting will protect you from malicious stuff in a template file, but I'm not going to guarantee it.
没有 sed,没有循环,只有毛茸茸的嵌套和引号。我很确定所有引用都会保护您免受模板文件中的恶意内容的侵害,但我不打算保证这一点。
回答by Adam Peck
You can still use sed to do the replace in a single pass. You just need to specify all the replacements in one command.
您仍然可以使用 sed 一次性完成替换。您只需要在一个命令中指定所有替换。
eg.
例如。
sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>
回答by David Poole
Building on the previous answer, perhaps use an array and compute the sed string?
基于上一个答案,也许使用数组并计算 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
Seems to fail on the multi-line strings, though.
不过,似乎在多行字符串上失败了。
I don't know how portable Bash arrays might be. Above snippet tested with "GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)"
我不知道 Bash 数组的便携性如何。上面的代码片段用“GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)”进行了测试
回答by Andor
My bash only solution:
我的 bash 唯一解决方案:
TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""
回答by L. Alberto Giménez
I just stumbled upon this question because I was just looking for the exact same, and I found envsubst(1).
我只是偶然发现了这个问题,因为我只是在寻找完全相同的,我发现envsubst(1).
You can use envsubstif you don't mind using environment variables:
如果您不介意使用环境变量,则可以使用envsubst:
PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline
string
2' envsubst < output.template
If you have a lot of variables you can store them in a file and just sourceit (remember to use exportat the end of the sourced file!)
如果你有很多变量,你可以将它们存储在一个文件中,并且只存储source它(记住export在源文件的末尾使用!)

