ZHUOWARE BACKYARD - NOTE INDEX|ZHUOWARE BACKYARD TOP|ZHUOWARE表ページ
Tcl exec command tips
はじめに
Tclのexecコマンドは,動かすのに多少ノウハウを要する.そのtipsとして,下記が非常に参考になる.
これでほぼOK!という感じなのだが,「変数に空白文字が含まれる場合や,あったりなかったりする語の,展開のさせ方」について,少しだけ補なってみた.
Feb. 22, 2009: ファイル名が"[", "]"を含む場合,下記ではevalで失敗することに気がついた.あらかじめ"[", "]"の前にescapeを挿入しておく必要がある.evalしなければよいのだが,いまのところよい方策が見つかっていない.
結局,
次のように書くとよい.setのたびにクォートや変数の展開が一段起きることを考え,evalにふさわしい形となるようコマンド文字列を構成しておいて,eval execする.
set filename "hoe hoe.tcl"
set option ""
# set option "-x"
set cmd "\"c:/program files/tcl/bin/wish84\" \"$filename\" $option"
eval exec $cmd
cmdを構成する行がポイントである.
- 空白を含む1語を構成するには,語をバックスラッシュ+ダブルクォートではさむ.
- 上の例の1,2語目は$filenameをそのようにして1語にしている.これにより,空白を含むファイル名に対応している.
- はさまないと,空白で区切られた別の語と解釈されるのでだめである.
- カーリーブレースではさむのでは,変数が展開されないのでだめである.
- 場合により,空文字列""となったり長さのある文字列となったりする変数は,そのままcmdの中に置く.
- 上の例の3語目のoption は,長さ0の文字列""となったり,"-x"という文字列になったりする.evalが,このような文字列を処理してくれるので,上記の例でよい.
難しい理由と,対策の手段
execの難しさとして,次のような点があげられる.
- コマンド名や各引数は,正しく分離されるように(間違ってくっつかないように)する必要がある.
- 空白文字を含む語は,正しく一体に保たれるように(間違って分離されないように)する必要がある.
- 語を入れたくない時には,正しく語が省かれるように(間違って「空文字列」の語が入らないように)する必要がある.
- バッククォートやダブルクォートが,正しく渡されるように(間違って,前処理の段階で解釈・変形されてしまわないように)する必要がある.
- 変数は正しく置換されるように(間違って,オリジナルのまま残らないように)する必要がある.
- システムごとに適合した表現になるようにする必要がある.
上記の要求を実現する手段として,次のようなものがある.
- eval. 変数を置換し,バックスラッシュ,ダブルクォート,カーリーブレースを解釈したうえ,語を空白で区切りなおす.
- バックスラッシュ,ダブルクォート,カーリーブレースの差異を考えて使う.ダブルクォートは変数を置換するがカーリーブレースは変数を置換しない.
- どのような過程をへてコマンド行がシステムにわたるかを考え,クォートをクォートする.
- fileコマンドのjoin機能(そのプラットフォームでの区切文字でpath名を構成してくれる)などを用いてシステム依存性を軽減する.
- どうしてもうまくゆかないときは,コマンド行を作り上げた後いったんテキストファイルとして保存し,それをシェルで実行させる.
そのほか
execするときは,エラー終了することも考え,catchするのがよい.
if {[catch {eval exec $cmd} msg]} {
puts "error: $msg"
} else {
puts "ok: $msg"
}