回答:
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 は、実行可能ファイルの実行が高速です。ここでの主な違いは、新しいシェルを起動せず(現在のシェルでコマンドを実行する)、新しいシェルを起動してから新しいシェルでコマンドを実行することです。新しいシェルの起動には時間がかかります。そのため、が遅いのです。echo
bash
/bin/echo
echo
bash -c
1.28s
eval
eval
bash -c
bash -c
eval
bash -c
したいと思います。eval
exec
bash -c
ていないことを悪い...
e='echo foo'; $e
うまく動作します。