2016-09-07 51 views
2

如果我贊同它包含$(主機名)命令字符串,然後正常工作。例如,在終端上運行:

echo "http://$(hostname)/main.html" 
http://artur/main.html 

但是,如果我從一個文件中的字符串(以前做的貓給一個變量),當我嘗試用回聲打印,它不工作:

$ cat site 
http://$(hostname)/main.html 
$ mysite=$(cat site) 
$ echo $mysite 
http://$(hostname)/main.html 

我在做什麼錯?任何想法?

+4

'$(貓站點)'可以用'$(<站點)'替換。 –

回答

10

殼進行變量擴展和外殼進行命令替換但它不這樣做他們遞歸:

  1. 一個變量擴展的結果將受到任何進一步變量擴展命令替換

  2. 一個命令替換的結果將不經受任何進一步變量擴展命令替換

這是一件好事,因爲,如果它被完成遞歸,會有意想不到的效果和安全問題的所有莊園。

一種解決方案是使用eval。這是一個普遍危險的方法,並應被視爲a last resort.

的安全解決方案是重新考慮你想要什麼。特別是,您想在什麼時候對hostname進行評估?在創建site文件之前是否應評估它?或者,應該在代碼最終運行時進行評估?後者似乎是你想要的。

如果是這樣的話,可以考慮這種方式。把%ssite文件在您想要的主機名去:

$ cat site 
http://%s/main.html 

當你讀site文件,使用printf在主機名代替:

$ mysite=$(printf "$(cat site)" "$(hostname)") 
$ echo "$mysite" 
http://artur/main.html 

使用bash,替代在形式上面是:

$ printf -v mysite "$(< site)" "$HOSTNAME" 
$ echo "$mysite" 
http://artur/main.html 
+1

在Bash中,你可以(主要)使用變量'HOSTNAME'而不是命令'hostname':'printf -v mysite「$(

+0

@gniourf_gniourf好點。回答更新爲使用'HOSTNAME'作爲bash解決方案。 – John1024

0

如果你只需要佔位符「主機」,由實際的主機名代替,你可以使用以下兩種方法之一:

與您現有的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