2016-09-07 10 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

'$(cat site)'は '$(

答えて

10

シェルは変数展開を実行し、シェルはコマンド置換を実行しますが、それは再帰的にそれらを行いません。

  1. 変数展開の結果はいずれにもさらされないますさらに変数展開またはコマンド置換

  2. コマンド置換の結果はないは、任意のさらなる可変膨張又はコマンド置換に供されます。

これは再帰的に行われた場合、予期しない結果とセキュリティ問題がすべて発生するため、これは良いことです。

1つの解決策は、evalを使用することです。これは一般的に危険なアプローチであり、a last resort.

としてください。安全な解決策は、あなたが望むものを再考することです。特に、hostnameはいつ評価されますか? siteファイルが作成される前に評価する必要がありますか?または、コードが最終的に実行されたときに評価する必要がありますか?後者はあなたが望むものであるように見えます。

この場合、この方法を検討してください。あなたがsiteファイルを読み込む場合は、ホスト名に置換するprintfを使用し、

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

:あなたは、ホスト名に行きたいsiteファイルに%sを入れ

$ 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':' printf -v mysite "$(

+0

@gniourf_gniourf良い点。 bashの解決策に 'HOSTNAME'を使うように更新されました。 – John1024

0

プレースホルダ 'hostname'だけを実際のホスト名に置き換える必要がある場合は、次のように使用できます。これらのいずれかの方法:

既存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 
関連する問題