変数に格納されているコマンドを実行するにはどうすればよいですか?


回答:


95

Unixシェルは、入力の各行で一連の変換を実行してから実行します。ほとんどのシェルでは、次のようになります(bashマンページから取得)。

  • 最初の単語分割
  • ブレース拡張
  • チルダ拡張
  • パラメータ、変数、および算術展開
  • コマンド置換
  • 二次単語分割
  • パス拡張(別名グロブ)
  • 見積もりの​​削除

$cmd直接使用すると、パラメーター拡張フェーズでコマンドに置き換えられ、その後、次のすべての変換が行われます。

を使用eval "$cmd"すると、引用符の削除フェーズまで何も実行されません。このフェーズ$cmdはそのまま返され、パラメータとしてに渡されますeval。この関数は、実行前にチェーン全体を再度実行することです。

したがって、基本的にはほとんどの場合同じであり、コマンドがパラメーター展開までの変換ステップを使用する場合は異なります。たとえば、ブレース拡張を使用します。

$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz

6
eval "$cmd"書かずに行う方法はeval$($cmd)${$cmd}
Steven Lu

2
@StevenLu、それらのどれも同等ではありません-意図的にそうです:eval操作はデータを構文として解析します。したがって、セキュリティに非常に敏感であり、暗黙的に実行することは非常に悪い形式になります。
チャールズ・ダフィー

5

(インタラクティブに、スクリプトで)実行するeval $cmd ときに実行cmd="ls -l"すると、目的の結果が得られます。あなたの場合、パターンのないgrepを持つパイプがあるので、grepパーツはエラーメッセージで失敗します。$cmd「コマンドが見つかりません」(またはそのような)メッセージを生成するだけです。したがって、エラーメッセージを生成するコマンドではなく、evalを使用して終了したコマンドを使用してみてください。


それは単なる誤植でした。「grep例外」である必要があります。
Volodymyr Bezuglyy 2011年

次に、$ cmd自体ではなく、evalを使用します。これはおそらく機能しないためです(私のテストでは、bashとzshでは機能しませんでした)。これは...にevalが行うことに意味されたものである
Henno Brandsma

0

$cmd変数をコマンドラインで実行される値に置き換えるだけです。 eval "$cmd"コマンドラインで結果の値を実行する前に、変数の展開とコマンド置換を行います

2番目の方法は、柔軟性のないコマンドを実行する場合に役立ちます。
for i in {$a..$b}
formatループは変数を許可しないため、機能しません。
この場合、bashまたはevalへのパイプが回避策です。

Mac OSX 10.6.8、Bash3.2.48でテスト済み


-4

私はあなたが置くべきだと思います

`

(バッククォート)変数の周りの記号。


4
これにより、コマンドの出力が実行されます。たとえば、ls -lの場合、「total」コマンドが見つかりません」のようなメッセージが生成されます(たとえば、total ...はls-lの出力の一部であるため)。 NOT何をしたい。
Henno Brandsma
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.