Shell Templates

We get lots of questions about how to use a template file, meaning a file with placeholders in it, which we want to replace with values at run time. There are a few different forms of this question, and as you would expect, a few different answers depending on the exact requirements.

The most basic requirement is what GNU autoconf uses: a pre-made template file with %PLACEHOLDER% things in it, and values in specific shell variables that we want to use. sed is well suited to this particular task:

 sed -e "s/%PLACEHOLDER%/$VARIABLE/g" \
     -e "s/%FIRSTNAME%/$firstname/g" \
     ... "$templatefile" > "$outputfile"

The notation %FOO% is what autoconf actually uses for its placeholders; hence its choice here. If the variables can contain slashes or newlines in their contents, then appropriate steps must be taken -- a different delimiter than slash can be used for the sed s/// command, but for newlines, you're advised to consult an advanced sed FAQ. Fortunately, the case where people want to include newlines in their substitutions, in this form of the question, is somewhat uncommon.

An alternative form of this question is, "I have a file with shell parameter expansions in it, like $foo. I don't know in advance what variables will be used, so I can't just make a list of all of them in a giant sed command." (Newlines in the variables are much more common here, but fortunately they do not present a problem with the solution we're about to give.)

This problem can be solved by constructing a HereDocument and feeding the result to a shell for expansion:

 { echo "cat <<EOF"
   cat "$templatefile"
   echo "EOF"
 } | sh > "$outputfile"

Recall that substitutions occur in the body of a here document as long as the sentinel (EOF in our case) is not quoted on the first line. We take advantage of that here.

Since the substitutions in the template file will be executed as shell code, it is important that a template file used in this way is under your control, and not generated by a user. You've been warned.


CategoryShell