Bash 在文件中一次性填充占位符

Bash 在文件中一次性填充占位符,bash,replace,sed,awk,textutils,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: Genera

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

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


在一次过程中完成我想要的任务的最佳方法是什么?

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

例如

sed-i的/PLACEHOLDER_1/string 1/g;s/占位符2/字符串2/g'

在前面的答案的基础上,可能使用数组并计算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
#/垃圾箱/垃圾箱
占位符[0]=“字符串1”
占位符[1]=“多行”
一串
2'
s=“sed-i”

对于((i=0;i有一种不用sed的方法:

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

blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2
PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
string 
2' envsubst < output.template 
还有剧本:

#! /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,没有循环,只有毛茸茸的嵌套和引号。我很确定所有的引号都可以保护您免受模板文件中恶意内容的攻击,但我不保证这一点。

我的bash唯一解决方案:

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

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

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

blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2
PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
string 
2' envsubst < output.template 
PLACEHOLDER\u 1='string 1'PLACEHOLDER\u 2='multiline
一串
2'envsubs

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

这是因为你需要在参数中有空格的周围加引号。将“sed-i”改为“sed-i”,在循环添加另一个引号后,它就可以工作了。你说“用bash测试”,但你的shebang说“sh”。sh在你的系统上与bash链接吗?如果是,它的行为是否与它的名称无关?sh在我的系统上是bash,但是(奇怪的是),它没有链接。我有/bin/sh和bin/bash,这是两个不同的文件。我想这是Mac的一个怪癖。我不知道GNU bash在被调用为“sh”与被调用为“bash”时是否会改变其行为。等号周围不能有空格。您可以在任一回音上使用-e来解释反斜杠转义,例如模板和/或pla中的\nceholders.Nope.不安全。模板可能包含“$(命令)”,这可能会产生不好的效果。您必须知道是否可以信任您的模板。您已经收到警告。谁在乎它是否安全,除非您将它提供给用户?我需要它根据我完全控制的内容自动生成一些html。:)+1!顺便说一句,如果需要在结果中保留引号,可以先使用sed转义它们:echo“$(eval“echo\”$(sed's/\“/\\\”/g'$template)\”)“>$outputfileThe
echo“$(eval“echo\”$template\)">$outputfile
在脚本中对我不起作用,但它在命令行中起作用。为什么?如果你真的知道自己在做什么并且不想进行备份,那么你需要在OSX上为-i选项提供一个空字符串:
sed-i''s/PLACEHOLDER\u 1/string 1/g;s/PLACEHOLDER\u 2/string 2/g'
…引用:不起作用,它似乎不起作用进行第二次传递。echo“AB”| sed's/a/B/g;s/B/a/g'返回AA,而不是BA。输入中a和B之间的换行符也会出现这种情况。您希望发生什么?您说的是替换a->B,但随后将其替换回B->a。您希望它们以独占方式执行还是作为单个表达式执行?