1. ホーム
  2. linux

[解決済み] Bashのevalコマンドとその典型的な使用法

2022-04-14 01:29:03

質問

bashのmanページを読んだ後、これに関して ポスト .

が具体的にどのようなものなのか、まだ理解できないでいます。 eval コマンドは何をするもので、どのような使い方が一般的でしょうか。例えば、次のような場合です。

bash$ set -- one two three  # sets $1 $2 $3
bash$ echo $1
one
bash$ n=1
bash$ echo ${$n}       ## First attempt to echo $1 using brackets fails
bash: ${$n}: bad substitution
bash$ echo $($n)       ## Second attempt to echo $1 using parentheses fails
bash: 1: command not found
bash$ eval echo \${$n} ## Third attempt to echo $1 using 'eval' succeeds
one

また、ドル記号とバックスラッシュはどのようにこの問題に関係しているのでしょうか?

どのように解決するのか?

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 はあまり使われません。いくつかのシェルでは、実行時まで名前がわからない変数の値を取得するのが最も一般的な使用方法です。bashの場合は ${!VAR} 構文があります。 eval は、演算子や予約語などを含む長いコマンドを作成する必要がある場合にも便利です。