eval
文字列を引数として取り、コマンド ラインでその文字列を入力したかのように評価します。(複数の引数を渡す場合、それらは最初にスペースで結合されます。)
${$n}
は bash の構文エラーです。中括弧内では、変数名のみを使用でき、いくつかの接頭辞と接尾辞を使用できますが、任意の bash 構文を使用することはできず、特に変数展開を使用することはできません。ただし、「この変数に名前が含まれる変数の値」という言い方があります。
echo ${!n}
one
$(…)
括弧内に指定されたコマンドをサブシェル (つまり、現在のシェルから変数値などのすべての設定を継承する別のプロセス) で実行し、その出力を収集します。シェルコマンドとしてecho $($n)
実行され、その出力が表示されます。は に評価されるため$n
、存在しないコマンド の実行を試みます。$n
1
$($n)
1
eval echo \${$n}
に渡されたパラメータを実行しますeval
。展開後のパラメータはecho
と${1}
です。コマンドeval echo \${$n}
を実行しecho ${1}
ます。
ほとんどの場合、変数置換とコマンド置換を二重引用符で囲む必要があることに注意してください (つまり、$
):がある場合はいつでも"$foo", "$(foo)"
。変数とコマンドの置換は、それらを省略する必要があることがわかっている場合を除き、常に二重引用符で囲んでください。二重引用符がない場合、シェルはフィールド分割を実行し (つまり、変数の値またはコマンドからの出力を個別の単語に分割します)、各単語をワイルドカード パターンとして扱います。例えば:
$ ls
file1 file2 otherfile
$ set -- 'f* *'
$ echo "$1"
f* *
$ echo $1
file1 file2 file1 file2 otherfile
$ n=1
$ eval echo \${$n}
file1 file2 file1 file2 otherfile
$eval echo \"\${$n}\"
f* *
$ echo "${!n}"
f* *
eval
はあまり使用されません。一部のシェルでは、最も一般的な用途は、実行時まで名前がわからない変数の値を取得することです。${!VAR}
bash では、構文のおかげでこれは必要ありません。eval
演算子、予約語などを含む長いコマンドを作成する必要がある場合は、引き続き便利です。