Filling placeholders in a file in one go

I have a skeletal text file with placeholder strings:

blah blah blah blah $PLACEHOLDER_1$ blah $PLACEHOLDER_2$ 

etc. The specific "form" of the placeholders does not matter - I can change them to what is most convenient for a particular implementation.

I have a bash script where I know the values ​​for the placeholders, and I need to generate a new file when replacing the placeholders with the values.

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

I can do this in a few passes using sed, but it's not fun. I use not to use Perl. I want to use only textutils and bash.

What is the best way to do what I want in one go?

+6
bash replace awk sed
source share
5 answers

You can use sed to replace in one pass. You just need to specify all replacements in one command.

eg.

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

Here is a way to do this without sed:

First, a slightly modified template file in which placeholders are bash variables:

 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 showing a template contained in a script, but with a twist. It also demonstrates default values ​​that can also be used in the template file version, plus you can do the 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 cycles, just hairy nesting and quotes. I am sure that the whole quote will protect you from harmful things in the template file, but I am not going to guarantee this.

+10
source share

Based on the previous answer, maybe use an array and compute the 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 

It seems that multiline strings failed.

I do not know how to transfer Bash arrays. The above snippet is tested using "GNU bash, version 3.2.17 (1) -release (i386-apple-darwin9.0)"

+5
source share

Only my bash solution:

 TEMPLATE=' foo $var1 bar $var2' eval "echo \"$TEMPLATE\"" 
+2
source share

I just stumbled upon this question because I was just looking for the same thing and found envsubst(1) .

You can use envsubst if you don't mind using environment variables:

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

If you have many variables, you can save them in a file and simply source (do not forget to use export at the end of the source file!)

+1
source share

All Articles