如果我回显一个包含 $(hostname)命令的字符串,那么它可以正常工作。例如,在终端中运行:
echo "http://$(hostname)/main.html"
http://artur/main.html
但是当我尝试使用echo进行打印时,如果我从一个文件中获取该字符串(以前将cat变为变量),则它不起作用:
$ cat site
http://$(hostname)/main.html
$ mysite=$(cat site)
$ echo $mysite
http://$(hostname)/main.html
我做错了什么?有什么想法吗?
答案 0 :(得分:10)
shell执行变量扩展,shell执行命令替换,但它不会递归执行:
变量扩展的结果将不进行任何进一步的变量扩展或命令替换
命令替换的结果将不进行任何进一步的变量扩展或命令替换
这是一件好事,因为如果它是递归完成的,那么会出现意想不到的结果和安全问题。
一种解决方案是使用hostname
。这是一种通常很危险的方法,应该被视为a last resort.
安全的解决方案是重新思考你想要的东西。特别是,您何时需要评估site
?是否应在创建%s
文件之前对其进行评估?或者,是否应该在代码最终运行时进行评估?后者似乎是你想要的。
如果是这种情况,请考虑这种方法。将site
放在您想要主机名称的$ cat site
http://%s/main.html
文件中:
site
当您阅读printf
文件时,请使用$ mysite=$(printf "$(cat site)" "$(hostname)")
$ echo "$mysite"
http://artur/main.html
替换主机名:
$ printf -v mysite "$(< site)" "$HOSTNAME"
$ echo "$mysite"
http://artur/main.html
使用bash,上述表单的替代方法是:
{{1}}
答案 1 :(得分:0)
如果您只需要占位符&#39;主机名&#39;要被实际主机名替换,您可以使用以下任一方法:
使用现有的site
文件:
$ 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
或者,如果您不介意更改site
文件内容,则有一个工具(通常用于此类用途)用实际值替换占位符: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