で次のコマンドを評価するeval <command>
方法は?eval
eval
評価用のシェルサブプロセスを作成しますか<command>
?それ以外の場合は、
eval
現在のシェルプロセスを使用して評価しますか?
気づく
eval
組み込みプロセスなので、それeval
自体では子プロセスは作成されません。<command>
実行前に子プロセスが組み込み<command>
プロセスであるかどうかに応じて、それを実行するために作成することも、生成しないこともあります。
上記のコマンドを評価するために使用されるシェルサブプロセスは、コメントに記載されている2つのうちの1つではありません。
ありがとうございます。
答え1
うまくいくのは、eval
パラメータの解析、変数の拡張などを実行してから、結果の文字列を正常に実行することです。
たとえば、次のようになります。
$ i=ls
$ eval $i
これは次のようにeval
置き換えられます。$i
ls
それからls
通常どおりコマンドを実行します(その後、プロセスが実行されfork()
ます)。exec()
ls
しかし、そうすれば
$ i="echo hello"
$ eval $i
hello
echo hello
これは組み込みプロセスとして実行されるため、新しいプロセスは作成されません。
変数を設定すると、シェルが作成されないことがわかります。
$ a=0
$ i="a=100"
$ eval $i
$ echo $a
100
$a
現在のシェル内で実行されている場合にのみ100に設定できます。
したがって、これはeval
実際にパーサ自体であり、現在のシェルで行われます。結果この文字列は、他のコマンドと同様に、新しいプロセスを作成することも、生成しないこともあります。
答え2
以下で何が起こっているのかわかりませんが、実際には次のように動作します。source somefile
新しいプロセスを作成せずに、現在のシェルプロセスでこれらのコマンドを実行します。
そして私は「コマンド」の代わりに「文字列」という言葉を使います。なぜならこれはまさに文字列だからです。これは機能しますが、次のコマンドはありません。
$ eval ""
あるいは、これは技術的にコマンドではありません。
$ eval "x(){ echo test;}"
$ x
test
そして常に新しいプロセスを作成するわけではないことを示すために(したがって私はウィリアムの意見に同意しません):
ターミナルから:
$ echo $$
9983
$ eval "sleep 100"
もう一つ:
$ ps -ef --forest
peter 9983 2840 0 14:21 pts/41 00:00:00 \_ /bin/bash
peter 17339 9983 0 14:26 pts/41 00:00:00 | \_ sleep 100
しかし、これを行うには、次の理由があります。
$ eval 'sleep 100' &
[1] 20675
$ ps --forest
PID TTY TIME CMD
9983 pts/41 00:00:00 bash
20675 pts/41 00:00:00 \_ bash
20676 pts/41 00:00:00 | \_ sleep
20757 pts/41 00:00:00 \_ ps
答え3
評価はこれだけのために新しいプロセスを作成しませんeval
。
代わりに、Evalは-引数接続を使用してパーサーを再実行しますeval
。
これにより、解析された結果が同じシェルで実行されます。ただし、引数がコマンドのサブシェルを生成する必要がある場合は、これが行われます。
したがって、evalの主な目的はパーサーを再実行することです。
答え4
これを試してみてください:評価中と$$
評価前の間を拡張します。''
$$
""
$ eval /bin/echo '$$' "$$"
17899 17899
したがって、両方とも同じプロセスで拡張されるため、evalで始まるサブシェルはありません。私はシェルではなく関数echoを使用しました。