シェルスクリプトを使用して変数の内容を印刷できますか? (間接引用)

シェルスクリプトを使用して変数の内容を印刷できますか? (間接引用)

次の変数を宣言するとします。

$ var='$test'
$ test="my string"

内容を印刷すると、以下が表示されます。

$ echo $var
$test

$ echo $test
my string

$varコンテンツの内容(たとえば、コンテンツ)を印刷する方法を見つけたいです$test。だから私は次を試してみます。

$ echo $(echo $var)
$test

しかし、結果は$testそうではありません"my string"。 bashを使用して変数の内容を印刷できますか?

答え1

$bashの間接変数拡張を使用してこれを行うことができます(変数から参照を省略できる限り):

$ var=test
$ test="my string"
$ echo "$var"
test
$ echo "${!var}"
my string

3.5.3 シェルパラメータの拡張

答え2

var含まれる変数名がプレフィックスで始まる場合は、次のものを$使用できますeval

$ var='$test'
$ test="my string"
$ eval echo $var
my string

ここで何が起こっていますか?

  • bashは$var値に拡張され、コマンドを$test生成しますeval echo $test
  • evalecho $test式を評価し、目的の結果を生成します。

一般的な使用はeval危険な場合があります(保存されている内容に応じてvar)、避けるのが最善です。あなたの場合は、間接拡張機能がより適切です(ただし、$ログインを削除する必要があります$test)。

答え3

〜のようにJesse_bの答えただし、変数間接参照の代わりに名前参照を使用します(bash4.3+が必要です)。

$ declare -n var=test
$ test="my string"
$ echo "$var"
my string

名前参照変数は、var参照する変数の名前を保持します。変数が逆参照されると、$var他の変数の値が返されます。

bash名前参照を再帰的に解決します。

$ declare -n var1=var2
$ declare -n var2=test
$ test="hello world"
$ echo "$var1"
hello world

完全性のために、連想配列(bash4.0以降)を使用することも、要件に応じてこの問題を解決する方法です。

$ declare -A strings
$ strings[test]="my string"
$ var=test
$ echo "${strings[$var]}"
my string

これは、動的に決定できるキーまたは名前を介して複数の値にアクセスするためのより柔軟な方法を提供します。特定のカテゴリのすべての値を単一の配列として収集したいが、まだいくつかのキー(ID固有の名前、宛先固有のパス名など)でその値にアクセスできる場合は、これはより良いオプションです。スクリプトの変数名前空間を汚染しません。

答え4

そしてzsh

$ var='$test'
$ test='*'
$ printf '%s\n' ${(e)var}
*

Bourneのようなシェルを使用してください。

$ eval 'printf "%s\n" "'"$var"'"'
*

zshこれらのシェルでは、分割+glob(例外)を防ぐために変数拡張を引用する必要があり、echo任意のデータと一緒に使用することはできません。

両方にシェルコード評価機能が(e)あるため、コンテンツを制御できるevalことが重要です。それ以外の場合は、任意のコマンド注入の脆弱性になる可能性があります(方法と同じ)。$var${!var}

関連情報