I've been doing alot of bash scripting the last few weeks. Struggling with all kinds of nasty problems and error handling stuff, I have discovered what a powerful utility this bash thing is.
Of course, when it comes to powerful scripting languages there's no substitute for Perl. Sometimes certain problems are a bit too complex for bash and it is nice to be able to fall back on Perl.
Let's say that I have an input file config.tmpl
with a single line containing [% base_url %]
and I want to generate a configuration file config
replacing the value of base_url
with $BASE_URL
as defined earlier in the bash script, e.g. BASE_URL=http://www.kiffingish.com/utils
.
One way of managing this is by using good old sed
like this:
cat config.tmpl | sed 's!\[% base_url %\]!'$BASE_URL'!' >config
Sure this is fine and dandy, but what do you do if you have multiple lines in config.tmpl
which need to be substituted on the fly? This is where Template Toolkit comes to the rescue.
I've added another line in config.in
containing [% index_file %]
which needs to be replaced with the value of $INDEX_FILE
. A bash one-liner with the help of Template Toolkit works wonders:
perl -MTemplate -e '$t = Template->new(); $t->process('config.tmpl', {base_url => '$BASE_URL', index_file => '$INDEX_FILE'})' > config
If you are bit paranoid, you can extend the above one-liner with some error checking just in case:
perl -MTemplate -e '$t = Template->new() || die "$Template::ERROR\n"; $t->process('config.tmpl',{base_url => '$BASE_URL', index_file => '$INDEX_FILE'}) || die $t->error()' >config
Now if you are like me and even more overcautious. one more sanity check is in order. Always expect the worst, and if this worst happens, make sure that you can trouble-shoot the situation quickly and efficiently.
That's why at the beginning of the bash script, I also double-check that the Template Toolkit module is indeed installed.
# Make sure that the Template Toolkit is installed
perl -MTemplate -e1 &>/dev/null
if [ $? -ne 0 ]
then
echo Template Toolkit is not installed, please install first.
exit $?
fi
Isn't the Template Toolkit truly magical? That's why I use it very often to help automate even the most complex chores. Thanks alot Andy.
Actually, there is a relatively simple way to use sed for multiple replacements, and that's by piping the results to a second sed instance, like this:
cat config.tmpl | sed 's!\[% base_url %\]!'$BASE_URL'!' | | sed 's!\[% index_file %\]!'$INDEX_FILE'!' >config
This can be extended for as many replacements as you want.
Also. the bash example above is not going to work (sorry) because of the extra single quotes in the command line which cause bash to choke with a syntax error. Here is the correct version:
perl -MTemplate -e '$t = Template->new(); $t->process('"'"''config.tmpl''"'"', {base_url => '$BASE_URL', index_file => 'yyyyy'})'
You need to escape the single quotes by using '"'"' which as it turns out is not so elegant after all.
Perhaps sed isn't so limited as claimed in this entry. Oh well, it was a challenging mental puzzle anyway.
Hi Kiffin,
Nice to read your blog :)
You might be interested to transform your sed to Perl like this:
cat config.tmpl | perl -ne 's/\[% base_url %\]/\$BASE_URL/;print' > config
The regex and the print are implicitly applied to $_
Also , I have a closer look at '"'"''$X''"'"'
If you write
p as '
q as " then
I tried to write it as pqp___qpp$Xppq___pqp , it was still hard to understand.(ignore the _)
Usually when these problems appear I escape with \
Can you explain how to parse the '"'"''$X''"'"' ?
Thanks