Memoize |
BasicWerk
EC Support
Technique
Facebook
|
20140809212217_shell_script_function_and_eval |
shell_script_function_and_eval
% ls file_1 file_2 file_3 other_1 other_2 other_3 % fname="file" # これは fname を展開した後、単なる文字列として file_* が残ってしまいパターンマッチが動作しない % ls "${fname}_*" ls: file_*: No such file or directory # 同じ理屈でこうしたところで動かない % ls `echo "${fname}_*"` ls: file_*: No such file or directory # これは動く % ls ${fname}_* file_1 file_2 file_3 # 別の見方をすると、これは動くけど % eval "ls ${fname}_*" file_1 file_2 file_3 # これは動かないってことだ % eval "ls \"${fname}_*\"" ls: file_*: No such file or directory
クォートの仕方一つで、文字列として評価されて終了するか、コマンドやパターンマッチとして評価されるか違ってくる。
そこの違いを踏まえて、function に(文字列やファイルではなく)コマンドを引数として渡してみよう。
# この単純な関数は、 function e0() { $1 } # 引数なしの ls を受け取った時はちゃんと動くけど、 % e0 ls file_1 file_2 file_3 other_1 other_2 other_3 # ls が引数を伴っているときは、$1 しか評価されない(=$2は捨てられる)ので # 単なる ls として評価される % e0 ls ${fname}_* file_1 file_2 file_3 other_1 other_2 other_3 # そして当然これは単なる文字列に評価されるから動かない % e0 "ls ${fname}_*" e0:1: command not found: ls file_* # 文字列の塊として渡されたコマンドラインを実行したくば eval を使う function e1() { eval $1 } % e1 "ls ${fname}_*" file_1 file_2 file_3 # eval は結局のところ文字列からパースするのだから、こんな書き方ができる。 function e2() { eval "$1" } # この関数の実装であれば、これも動くし、 % e2 ls file_1 file_2 file_3 other_1 other_2 other_3 # これも動く % e2 "ls ${fname}_*" file_1 file_2 file_3 # あーだからこうすると、 function e3() { eval "$*" } # これは結局、一つ余計にコマンドを打たなきゃいけないだけのシェルだ。 % e3 ls ${fname}_* file_1 file_2 file_3
|
© Shin Nakamura/BasicWerk 2014 |