Reputation: 1296
I read a string from a file with shell script variables, and want to substitute the variables with values in a function like
hello.txt:
-------------
Hello $NAME
a.sh
-------------
function printout
{
echo ???somehow_parse??? $1
}
NAME=Joe
printout "$(cat hello.txt)"
NAME=Nelly
printout "$(cat hello.txt)"
The example is not the best, but it describes my problem. In other words: can I use shell as a template engine?
I am using ksh.
Upvotes: 3
Views: 1209
Reputation: 6551
I think the easiest solution is to use the basename
utility.
For instance, if you have the following string: a='/home/you/stuff/myfile.txt'
you could use commands like:
dirname $a
basename $a
basename $a .txt
and get output that looks like this:
/home/you/stuff
myfile.txt
myfile
Upvotes: 0
Reputation: 86924
In general, I would go for a search-and-replace approach using sed/awk such as that shown in Kent's answer or this answer.
If you want a shell-only approach, then the standard way would be to use eval
. However, this poses a security risk. For example:
[me@home]$ cat hello.txt
hello $NAME; uname -a
[me@home]$ NAME="shawn"
[me@home]$ eval echo "`cat hello.txt`" # DO NOT DO THIS!
hello shawn
Linux SOMEHOST 2.6.9-101.ELsmp #1 SMP Fri May 27 18:57:30 EDT 2011 i686 i686 i386 GNU/Linux
Notice how a command can be injected into the template!
You can however reduce the risk using this approach:
[me@home]$ eval "OUT=\"`cat hello.txt`\""
[me@home]$ echo $OUT
hello shawn; uname -a
Do note that this is still not foolproof as commands can still be injected using $(cmd)
or `cmd`
.
In short, you should use eval
only if you understand the risks and can control/limit access to the template files.
Here's an example of how this can be applied in your script:
function printout {
FILENAME=$1
eval "OUT=\"`cat $FILENAME`\""
echo $OUT
}
NAME=Joe
printout hello.txt
NAME=Nelly
printout hello.txt
Upvotes: 1
Reputation: 40414
If you're sure that the contents of your template file is completely safe, that is, it doesn't contain a string to execute a command that might harm your computer, then you can use eval:
#!/bin/bash
NAME=Joe
TEMPLATE=$(cat hello.txt)
eval "echo $TEMPLATE"
NAME=Nelly
eval "echo $TEMPLATE"
Example output:
HELLO Joe
HELLO Nelly
Upvotes: 1
Reputation: 195169
like this?
kent$ head hello.txt t.sh
==> hello.txt <==
hello $name
==> t.sh <==
#!/bin/bash
function printout
{
echo $1|awk -v name="$name" 'gsub(/\$name/,name)'
}
name=xxx
printout "$(cat hello.txt)"
name=yyy
printout "$(cat hello.txt)"
run it:
kent$ ./t.sh
hello xxx
hello yyy
Upvotes: 0