Articles RSS Feed

Blite Blog

Blite : a lightweight blog app

Loading Variables into a Template with Bash

Posted 7 Mar 2011, 1:16 pm in Scripts

Here's a simple and efficient method of loading variables into a webpage template with a Bash CGI script.

I've been rewriting a website using Bash scripting, and, for ease of design and maintainance, I wanted to have a page template separate from the actual scripts.

To make it work, my thinking was I had to read the template and then substitute values for variables in the template. I got it working initially with Bash string substitutions, like this:

TEMPLATE=`cat template.txt`
TEMPLATE=$((TEMPLATE//#TITLE#/$TITLE))

(In template.txt there's a placeholder #TITLE# for the $TITLE variable.)

But then I ran into a problem. With each variable I added, the Bash script got slower. The complete script, with all variables in place, was taking almost 2 seconds to run! Needless to say that wasn't acceptable performance for a public web script.

So I set out to find a more efficient manner of using templates in Bash. Googling turned up lots of resources like this page that offers solutions using eval, sed and even perl. I tried all these approaches (and more) without satisfactory results. Performance was still very poor.

I put the problem away for a few days and then came back to it, determined to start from scratch. With all thoughts of eval, sed, awk, perl, etc. banished, the solution turned out to be rediculously simple.

#!/bin/bash
TITLE="Hello World"
TODAY=`date +'%A, %B %d, %Y'`
echo "Content-type: text/html"
echo ""
source template.txt

The template file (template.txt) looks like this:

echo "
<html> 
<head> 

<title>${TITLE}</title>
</head>
<body>
<h1>${TITLE}</h1>
<p>Today is ${TODAY}</p>
</body>

</html>
"

Simple, clean and fast. Just remember than any double quotes in the template must be escaped with a backslash. For simplicity I just use single quotes for HTML attributes and inline CSS.

Performance of my web script is now blazing-fast -- it runs in about 0.014 second, compared to the previous two seconds :)

3 Comments
Comments RSS Feed
Craig Barnes:
I was using this idea for a while but it started to bother me that I had to include the echo command in all my templates, so I switched to this solution:

render () {
eval "echo \"$(cat $1 | tr \" \')\""
}

render header.html
render body.html
render footer.html

The function is somewhat uglier than just using the "source" builtin but it allows you to remove the "echo" commands from your templates. It also pipes the template through tr to automatically convert all double quotes to single quotes.
14 Oct 2011, 10:33 pm · Permalink
why not this?
echo this is what I want to %REPLACE% right here. |sed 's/%REPLACE%/kick/g'
20 Oct 2011, 7:23 pm · Permalink
Craig Barnes:
@ man of linux

Yeah that's fine for replacing a few variables but it becomes hard to read and maintain if you use it for large HTML templates. Or more specifically, it's not a template system...it's just sed.
22 Oct 2011, 1:03 am · Permalink
Comments are closed for this post.