Reputation: 31
If I echo a string which contains the $(hostname) command, then it works fine. For example, run in terminal:
echo "http://$(hostname)/main.html"
http://artur/main.html
But if I get that string from a file (previously doing cat to a variable) when I try to print with echo, it does not works:
$ cat site
http://$(hostname)/main.html
$ mysite=$(cat site)
$ echo $mysite
http://$(hostname)/main.html
What am I doing wrong? Any idea?
Upvotes: 3
Views: 7131
Reputation: 113864
The shell performs variable expansion and the shell performs command substitution but it does not do them recursively:
The result of a variable expansion will not be subjected to any further variable expansion or command substitution.
The result of a command substitution will not be subjected to any further variable expansion or command substitution.
This is a good thing because, if it was done recursively, there would be all manor of unexpected results and security issues.
One solution is to use eval
. This is a generally dangerous approach and should be regarded as a last resort.
The safe solution is to rethink what you want. In particular, when do you want hostname
evaluated? Should it be evaluated before the site
file is created? Or, should it be evaluated when the code is finally run? The latter appears to be what you want.
If that is the case, consider this approach. Put %s
in the site
file where you want the host name to go:
$ cat site
http://%s/main.html
When you read the site
file, use printf
to substitute in the host name:
$ mysite=$(printf "$(cat site)" "$(hostname)")
$ echo "$mysite"
http://artur/main.html
With bash, an alternative for the form for the above is:
$ printf -v mysite "$(< site)" "$HOSTNAME"
$ echo "$mysite"
http://artur/main.html
Upvotes: 10
Reputation: 20980
If you only need the placeholder 'hostname' to be replaced by actual hostname, you could use either of these methods:
With your existing site
file:
$ cat site
http://$(hostname)/main.html
$ mysite=$(sed 's|\$(hostname)|'"$(hostname)"'|g' site) # or
$ mysite=$(awk '{print gensub("\\$\\(hostname\\)",hostname,"g", $0);}' "hostname=$(hostname)" site)
$ # Note: Above `sed` based method has risk of shell injection. `awk` option is safer.
$ echo "$mysite"
http://artur/main.html
Or if you don't mind changing your site
file contents, there is a tool, which is typically used for such purposes - to replace placeholders by actual values: m4 - macro processor
$ cat site
http://HOSTNAME/main.html
$ # HOSTNAME is the placeholder here; can be any identifier string.
$ mysite=$(m4 -D "HOSTNAME=$(hostname)" site)
$ echo "$mysite"
http://artur/main.html
Upvotes: 0