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
演算子や予約語などを含む長いコマンドを作成する必要がある場合は、引き続き役に立ちます。
eval は単に「実行前に式をもう一度評価する」と考えてください
eval echo \${$n}
echo $1
になります 最初の評価の後。注意すべき 3 つの変更点:
\$
$
になりました (バックスラッシュが必要です。それ以外の場合は、${$n}
を評価しようとします 、これは{$n}
という名前の変数を意味します 、許可されていません)$n
1
と評価されましたeval
消えた
2周目は基本的にecho $1
直接実行できます。
つまり eval <some command>
最初に <some command>
を評価します (ここでの評価とは、変数を置換する、エスケープ文字を正しい文字に置き換えるなどを意味します)、結果の式をもう一度実行します。
eval
変数を動的に作成する場合、またはこのように読み取るように特別に設計されたプログラムから出力を読み取る場合に使用されます。例については、http://mywiki.wooledge.org/BashFAQ/048 を参照してください。リンクには、eval
の典型的な方法もいくつか含まれています。 の使用、およびそれに伴うリスク。
私の経験では、eval の「典型的な」使用法は、シェル コマンドを生成して環境変数を設定するコマンドを実行することです。
おそらく、環境変数のコレクションを使用するシステムがあり、設定する変数とその値を決定するスクリプトまたはプログラムがあるとします。スクリプトまたはプログラムを実行するときはいつでも、フォークされたプロセスで実行されるため、環境変数に対して直接行うことは、終了時に失われます。ただし、そのスクリプトまたはプログラムはエクスポート コマンドを stdout に送信できます。
eval がなければ、stdout を一時ファイルにリダイレクトし、一時ファイルを入手してから削除する必要があります。 eval を使用すると、次のことができます。
eval "$(script-or-program)"
引用符が重要であることに注意してください。この (不自然な) 例を見てみましょう:
# activate.sh
echo 'I got activated!'
# test.py
print("export foo=bar/baz/womp")
print(". activate.sh")
$ eval $(python test.py)
bash: export: `.': not a valid identifier
bash: export: `activate.sh': not a valid identifier
$ eval "$(python test.py)"
I got activated!