シェル変数名を別の変数に変更する

シェル変数名を別の変数に変更する

私はbashしばらく変数を置き換えるのに苦労しましたが、これはわかりません...

コマンドテンプレートを含む変数があります。

CMD_TMPL='sudo -u ${USER_NAME} ${USER_HOME}/script.sh'

変数USER_NAMEsumはUSER_HOME後でスクリプトで計算され、まだ定義CMD_TMPLされていることは知られていません。したがって、コマンドは一重引用符で囲まれており、置き換えられませんでした。

その後、スクリプトは私が含めるタスクを実行したいことUSER_NAME=testを理解しています。USER_HOME=/home/test${CMD}

sudo -u test /home/test/script.sh

以下のスクリプトはパイプラインでコマンドを使用します。たとえば、次のようになります。

${CMD} | output-processing.sh

変数名から${CMD_TMPL}変数値への拡張を実装するには${CMD}?私はいろいろなechoことを試しましたが、それをeval見つけることはできません。

ありがとうございます!

ベストアンサー1

コードを保存するために使用される特別な型の変数があります。機能:

cmd_tmpl() { sudo -u "$USER_NAME" "$USER_HOME/script.sh" "$@"; }
cmd() { cmd_tmpl other args "$@"; }
cmd | output_processing...

別のアプローチは、変数をコマンドライン(シェルコード)として処理し、最終的に次を使用してそのコードを解釈することですeval

cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
cmd=$cmd_tmpl' other args as shell code'
eval "$cmd" | output_processing...

使い方$cmd | output_processingが間違っています。$cmdこれはスカラー変数であり、分割+glob演算子を使用して単純なコマンドの引数リストを取得すると、ここに格納されているコマンドラインを評価しません。したがって、これは限られた条件でのみ機能します。

単純なコマンドのパラメータを配列に保存できます。

cmd=(sudo -u "$USER_NAME" "$USER_HOME/script.sh" ...)
"${cmd[@]}" | post_processing

ただし、これは変数の遅延拡張には役立ちません。

次の方法で拡張を延期できます。

cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
...
eval "cmd=($cmd_tmpl)" # now expanded
cmd+=(other args)
"${cmd[@]}" | post-processing

(環境にエクスポートした変数の場合は、変数名をすべて大文字で予約するのが最善です。)

おすすめ記事