Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Say I have a shell configuration file config like this:

HOST=localhost
PORT=8080

Now I have a template template like this:

The host is <%= @HOST %>
The port is <%= @PORT %>

How do I substitute placeholders in template with values in config file?

I can certainly do it like this:

$ . config
$ sed -e "s/<%= @HOST %>/$HOST/" \
> -e "s/<%= @PORT %>/$PORT/" < template
The host is localhost
The port is 8080

But if there are many config values this becomes too cumbersome. How would I do this in more generic way? I would like to iterate over each placeholder and substitute it with a real value.

share|improve this question

3 Answers 3

up vote 3 down vote accepted

You could do something like:

eval "cat << __end_of_template__
$(sed 's/[\$`]/\\&/g;s/<%= @\([^ ]*\) %>/${\1}/g' < template)
__end_of_template__"

That is, have sed replace all the <%= @xxx %> with ${xxx} after having escaped all the $, \ and ` characters and let the shell do the expansion.

Or if you can't guarantee that template will not contain a __end_of_template__ line:

eval "cut -c2- << x
$(sed 's/[\$`]/\\&/g;s/<%= @\([^ ]*\) %>/${\1}/g;s/^/y/' < template)
x"
share|improve this answer

An awk way:

awk -F= 'FNR==NR{v[$1]=$2;next};{for(p in v)gsub("<%= @"p" %>",v[p])};1' config template

Updated according to Stephane Chazelas' comment to allow “=” signs in the values:

awk -F= 'FNR==NR{v[$1]=substr($0,length($1)+2);next};{for(p in v)gsub("<%= @"p" %>",v[p])};1' config template
share|improve this answer
    
Note that that assumes that the value of the parameters don't contain "=" characters or the name of another parameter (like FOO="<%= @BAR %>") –  Stéphane Chazelas Dec 6 '12 at 13:33

One way:

#!/bin/sh

. config

while read line
do
        eval echo $(echo $line | sed "s/\([^<]*\)<%= @\([^ ]*\) %>/\1 \$\2/")
done < template

Results:

The host is localhost
The port is 8080

Using sed, we extract the characters till '<' and form a group(\1), and extract the placeholder and form another group(\2). This is substituted with the 1st group and then the dollar symbol followed by 2nd group. Just by using the eval command, the variable can be evaluated and gets expanded.

share|improve this answer
    
Lines containing shell special characters will be seriously mangled and may cause your script to execute arbitrary code. If the input comes from a non-trusted source, this is a glaring security hole. You need to do some serious quoting and escaping to make this work. (See Stephane Chazelas's answer for an example of how to do it right.) –  Gilles Dec 6 '12 at 23:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.