回答:
eval "$1"現在のスクリプトでコマンドを実行します。現在のスクリプトのシェル変数の設定と使用、現在のスクリプトの環境変数の設定、現在のスクリプトの関数の設定と使用、現在のスクリプトの現在のディレクトリ、umask、制限、およびその他の属性の設定などが可能です。bash -c "$1"環境変数、ファイル記述子、およびその他のプロセス環境を継承する(ただし、変更を送信しない)完全に独立したスクリプトでコマンドを実行しますが、内部シェル設定(シェル変数、関数、オプション、トラップなど)は継承しません。
(eval "$1")サブシェルでコマンドを実行する別の方法があります。呼び出しスクリプトからすべてを継承しますが、変更を送信しません。
例えば、変数があると仮定dirエクスポートされない$1でcd "$foo"; ls、その後、:
cd /starting/directory; foo=/somewhere/else; eval "$1"; pwdの内容をリストし、/somewhere/else印刷し/somewhere/elseます。cd /starting/directory; foo=/somewhere/else; (eval "$1"); pwdの内容をリストし、/somewhere/else印刷し/starting/directoryます。cd /starting/directory; foo=/somewhere/else; bash -c "$1"; pwd/starting/directory(cd ""現在のディレクトリを変更しないため)の内容をリストし、を出力し/starting/directoryます。(eval "$1")とは何の関係もありませんsource。それはちょうどの組み合わせだ(…)とeval。source fooはとほぼ同等eval "$(cat foo)"です。
evalとは.dotつまりevalと作品の引数と.dotして動作しますファイル。
間の最も重要な違い
bash -c "$1"
そして
eval "$1"
前者はサブシェルで実行され、後者は実行されないということです。そう:
set -- 'var=something'
bash -c "$1"
echo "$var"
#there doesn't seem to be anything here
set -- 'var=something'
eval "$1"
echo "$var"
something
bashしかし、なぜだれかがそのように実行可能ファイルを使用するのか、私にはわかりません。呼び出す必要がある場合は、POSIX保証付きの組み込みを使用してくださいsh。または(subshell eval)、環境を保護する場合。
個人的には、何よりもシェルが好き.dotです。
printf 'var=something%d ; echo "$var"\n' `seq 1 5` | . /dev/fd/0
something1
something2
something3
something4
something5
実際にどちらかを使用する唯一の原因は、変数が実際に別の変数を割り当てたり評価したりする場合、またはワードスプリットが出力にとって重要な場合です。
例えば:
var='echo this is var' ; $var
this is var
それは機能しますが、echoそれは引数の数を気にしないからです。
var='echo "this is var"' ; $var
"this is var"
見る?の二重引用符は、のシェルの展開結果が$var評価されないために現れquote-removalます。
var='printf %s\\n "this is var"' ; $var
"this
is
var"
しかし、evalまたはsh:
var='echo "this is var"' ; eval "$var" ; sh -c "$var"
this is var
this is var
を使用するevalかsh、シェルが展開の結果で2番目のパスを取得し、それらを潜在的なコマンドとしても評価すると、引用符が違いを生じます。次のこともできます。
. <<VAR /dev/fd/0
${var:=echo "this is var"}
#END
VAR
this is var
私は簡単なテストを行いました:
time bash -c 'for i in {1..10000}; do bash -c "/bin/echo hi"; done'
time bash -c 'for i in {1..10000}; eval "/bin/echo hi"; done'
(はい、bash -cを使用してループを実行しましたが、違いはありません)。
結果:
eval : 1.17s
bash -c : 7.15s
だから、eval高速です。のmanページからeval:
evalユーティリティは、引数を文字で区切って連結し、コマンドを作成します。構築されたコマンドは、シェルによって読み取られて実行されます。
bash -cもちろん、bashシェルでコマンドを実行します。1つのメモ:を使用してシェルが組み込まれている/bin/echoため、新しいプロセスを開始する必要がないことを意味します。交換してのためのテスト、それがかかりました。それはほぼ同じです。Hovever は、実行可能ファイルの実行が高速です。ここでの主な違いは、新しいシェルを起動せず(現在のシェルでコマンドを実行する)、新しいシェルを起動してから新しいシェルでコマンドを実行することです。新しいシェルの起動には時間がかかります。そのため、が遅いのです。echobash/bin/echoechobash -c1.28sevalevalbash -cbash -ceval
bash -cしたいと思います。evalexec
bash -cていないことを悪い...
e='echo foo'; $eうまく動作します。