Bash无法回显嵌入变量的$(hostname)

时间:2016-09-07 02:44:30

标签: bash echo hostname

如果我回显一个包含 $(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

我做错了什么?有什么想法吗?

2 个答案:

答案 0 :(得分:10)

shell执行变量扩展,shell执行命令替换,但它不会递归执行:

  1. 变量扩展的结果将进行任何进一步的变量扩展命令替换

  2. 命令替换的结果将进行任何进一步的变量扩展命令替换

  3. 这是一件好事,因为如果它是递归完成的,那么会出现意想不到的结果和安全问题。

    一种解决方案是使用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