風来坊@真幸福知

出雲市 福知寺 行事ご案内 坐禅会 日記 テクノロジー English Zazen session technology Korean 한국어 참선 묵조선 텍놀로지

Gnuplot: "!mv out.eps plt-01.eps"がダメな件

Gnuplotは20年愛用しているし, 気まぐれでつくったpointnumberパッチも本家に取り入れてもらって感謝している. ところがひとつだけ気に入らないところがある.

gnuplot> plot なんたらかんたら

gnuplot> load "outepsc20"

gnuplot> !mv out.eps plt-001.eps

"outepsc20"はプロットをEPSファイル"out.eps"に出力するスクリプト. 何か描いてEPSにする作業は頻繁にやるので$GNUPLOT_LIBで指定したパスに置いておいて簡単に呼び出せるようにしてある.

上のようなことをやると, エラーが出る.

gnuplot> !mv out.eps plt-01.eps
^
"plot.gp", line 6: expecting exponent

ソースを調べてみると, このエラーはget_num()という関数で出ている. つまりgnuplotコマンドラインを解釈して, 数値に続いて"e"または"E"があると, これは1.23e4などのように10の何乗を意味するものだから当然eやEに続いてもうひとつ数値があるはずと思って, それがないからダメといっている.

ここで変だと思われるのは, シェルのコマンドだと言ってる"!"に続く文字列を, どうしてgnuplotが解釈する必要があるのか??ということ. また, シェルコマンドを実行するもうひとつの方法であるsystem()を使うと,

gnuplot> system('mv out.eps plt-01.eps')

これは問題なく実行される.

バグなのかなぁ...こんなのけっこう当たりそうだけど誰も気づいてないのかなぁ...と思ってgnuplot-beta MLにメールを書こうとするが...ふと思いとどまってググると,

gnuplot / Bugs / #1517 shell command line parsing error?

これは知られているけどこういうことになっているらしい. つまり,

  • !.... はシェルに与えるコマンドをgnuplotによって解釈してからシェルに渡す
  • system('....') は引数が' 'や" "で囲まれて文字列になっているのでそのままシェルに渡す

ということ. ちなみに, plt-01.epsを' 'で囲んで書くと!でもうまくいく.

gnuplot> !mv out.eps 'plt-01.eps'

!... がシェルに渡される前にgnuplotによって解釈されるということのご利益のひとつは, マクロを展開してからシェルで実行できるということかもしれない. 例えばターゲットのファイル名をマクロで定義してから処理するとか...

gnuplot> fo='plot-01.eps'

......

!mv out.eps @fo

こんな感じにすれば, 数字入りのファイル名で出力したいときに悩まなくて済むかも. !mv...の行も"outeps..."の中に書いてしまえばいいのかな!?... 今までさんざん使ってきた常用スクリプトをいじることになるが...

....

結局, こういうスクリプトにしとけば....

# e.g. call "fo-epsc" "plt-001.eps"
setout="set output '" . ARG1 . "'"
set term push
set term postscr eps enhanced color "Helvetica" 17
@setout
replot
set term pop
set output

こんな感じでEPSを出せるし, 番号付きファイル名も気にしなくてOK.

gnuplot> plot なんたらかんたら

gnuplot> call "fo-epsc" "plt-001.eps"

... 私にとってのGnuplot生活2.0が始まる?

まぁ, この件も気に入らないわけでもないかも(笑)

追記: これをやりながら気づいたのだが, Gnuplotでマクロを使うためにやってた"set macros"はもう要らなくなったらしい. 5.0まではあった. 今も古いスクリプトでトラブらないようにあってもエラーを吐かないが, 5.2では常にマクロは有効とのこと@@

追記: callを使う場合のファイル名指定の引数の中に, 出力ディレクトリを定義したマクロを使おうとするとうまく行かない.

gnuplot> call "fo-epsc" "@plt/plt-001.eps"

gnuplot> call "fo-epsc" @plt/plt-001.eps

上の例ではマクロが展開されない. 一方, " "をつけないとマクロは展開されるが文字列引数として渡されないようだ. 以下のようにするとうまく行く. つまりマクロではなくpltを文字列変数として, "/plt-001.eps"と連結してから読ませる.

gnuplot> call "fo-epsc" plt."/plt-001.eps"