eval - コマンドを実行


引数とした文字列をコマンドと解釈して実行します。

Table of Contents

Edit

たとえば

% eval cd /

とすれば cd / を実行します。"cd /" のようにしたほうが安全かもしれません。 引数の文字列は複数個でもかまいません。連結して実行されます。

正確にはevalは引数を一度「評価」し、それらを改めてコマンドとして実行します。「評価」とは変数を展開することです。

% set x='ls -d $HOME' (csh, tcsh の場合)
% $x
ls: $HOME: No such file or directory

シングルクォーテーションの場合、変数は展開されずに格納されるため、 $HOME という文字として扱われている。

% eval $x
/home/student/s1080134

$HOME を展開してくれている。

このように、文字列を評価しコマンドを実行する eval は、シェルに限らずC言語など様々な言語で採用されているので覚えてよくと便利な時がきっと来ます。

シェルスクリプト内での使用 Edit

eval は基本的にはシェルスクリプト内で使います。

#!/bin/bash
num=1
while [ $num -le $# ] ; do
   eval echo "Argument $num is \$$num"
   num=`expr $num + 1`
done	

この

eval echo "Argument $num is \$$num"

の部分は eval によって

echo "Argument 1 is $1"

のように置き換えられこのコマンドが実行されます。

% bash [このシェルスクリプトファイル] a b c

のようにして試してみてください。 sh, bash スクリプトでは $1 が第一引数、$2 が第二引数を、以下略を意味します。 よって、

Argument 1 is a
Argument 2 is b
Argument 3 is c

のようになるはずです。

一応ついでに説明しておきますと、$# が引数の数で、-le は less or equal (<=) を意味します。

find との併用 Edit

自分はコマンドラインでは例えば find コマンドを使用してなにか行うときにいきなり exec するとこわいので、まず

find -exec echo "コマンド ;" \;

のように echo で実験をしてから

eval `find -exec echo "コマンド ;" \;`

のように実行したりします。` ` で ` ` 内のコマンドの出力を他のコマンドの引数とすることができます。 ミソは

echo "コマンド ;"

の ; (セミコロン) で、これをつけておかないと、例えば特に意味はないですが

ls [file1]
ls [file2]
ls [file3]

という実行を期待して

eval `find -exec echo "ls {}" \;`

のようにしてしまうと、

ls [file1] ls [file2] ls [file3]

となり1つの ls コマンドになってしまいます。

eval `find -exec echo "ls {}; " \;`

ならば

ls [file1]; ls [file2]; ls [file3]

のように ; でコマンドが区切られるので期待通りの動作をします。便利な例としては

% eval `find -exec echo "sed 's/[regexp]/[string]/g' {} > /tmp/tmp; \mv /tmp/tmp {};" \;`

こんなのいかがでしょうか?カレントディレクトリ以下のすべてのファイル中の文字列を置き換えます。

最後にまた、シェル変数を使用しようとすると一度展開されてしまうことを忘れずに。 コマンドラインではそうそうシェル変数を使用しないと思いますが、たまにはまります。

2段評価 Edit

% eval echo 'ls -d \$HOME'
ls -d /home/student/1080134

とすれば変数を評価した結果の文字列を得ることができるので、 その後また eval すれば2段評価になりますね。 この例だと2回目に変数がないですが。


xrea