Develop and Download Open Source Software

OpenSource Downloads

7-Zip  (4,208)  
HandBrake Japanese Language Version  (3,353)  
CrystalDiskInfo  (1,743)  
CotEditor  (1,120)  
CrystalDiskMark  (866)  
Boookends  (788)  
SMPlayer  (642)  
えこでこツール  (599)  
Tera Term  (595)  
10  FFFTP  (579)  
11  Cabos  (530)  
12  BathyScaphe  (494)  
13  ffdshow  (481)  
14  MergeDoc  (464)  
15  ギコナビ  (438)  
More >>

最近ブックマークされた記事

bashシェルに新機能を追加するBashDiff(パート2)

2008年11月05日 12:43 Ben Martin 1 2 3

 前回の記事では、bashシェルの機能を拡張するBashDiffというパッチについて紹介した。BashDiffの適用によりbashで利用可能となるコマンドや文字列の構文解析については、先に解説したとおりである。今回はその続きとして、位置パラメータの操作法、XMLの構文解析、ISAMやリレーショナルデータベースとの通信、GTK+2 GUIの作成、その他若干のテクニックや注意事項を紹介することにする。

位置パラメータの操作

 BashDiffから提供される位置パラメータの操作用コマンドは、多くの場合、ノーマル状態のbashよりもかなり効率的な処理を可能にしてくれる。例えばその1つであるpcursorは、複数の位置パラメータにおける現在値を1つのグループにまとめて取り扱えるようにし、これらのクリアおよび、スタックへの待避や取り出しを一括して扱うためのコマンドだ。位置パラメータそのものを操作するその他の追加コマンド群には、pp_というプレフィックスが付けられている。またオプション扱いではあるが、これらのコマンドでは-aパラメータを指定することで、明示的な名前を付けた配列にて位置パラメータを格納させることも可能だ。例えば下記のサンプルは、ノーマル状態およびBashDiff適用後のbashにおける位置パラメータの追加コマンドを比較したものである(後者が下側)。

$ set -- $@ Z
$ pp_append Z

 実際、pp_系コマンドの多くは、ノーマル版bashシェルでの操作よりも処理速度が大幅に向上している。もっとも、pp_プレフィックスの付いたコマンド群がどの程度有用かは、個々のユーザにおける位置パラメータの使用頻度で決まるものであるが、その効果は特にループ処理にて顕著に現れることになるだろう。例えば下記のサンプルコードはその極端な実装例で、負荷の大きいプリペンド操作を1つのループ中で1,000回実行させている。この実行結果を見ると、pp_バージョンのコードの方が非常に効率的な処理となっていることが分かるだろう。ただしループ回数を100に下げた場合、ノーマル版bashコマンドでも0.15秒で終了している。確かにこの場合においてもBashDiff版の方が所要時間0.006秒という点で高速ではあるが、こうした位置パラメータ操作の100回ループが他のスクリプトから何度も呼び出されるのでなければ、ノーマル版bashの処理であっても許容範囲内と見なせるかもしれない。

$ pp_trim 10000
$ time for i in `seq 1 1000`; do set -- Zoldpre $@; done

real	0m10.157s
user	0m9.880s
sys	0m0.004s

$ pp_trim 10000
$ time for i in `seq 1 1000`; do pp_push Zoldpre; done

real	0m0.088s
user	0m0.036s
sys	0m0.002s

XMLファイルのパース

 次にBashDiffでサポートされる、ExpatというXMLパーサについて見てみよう。このexpatビルトインの呼び出しで処理できるのは、1度に1つのXMLファイルだけだが、XMLの処理中はその中に含まれる、エレメント、コメント、名前空間などが検出されるごとに、指定した1群のコールバックが呼び出されていく。そしてBashDiffは、いくつかのハウスキーピング作業をユーザの代わりに自動で処理してくれる。例えば、XML_TAG_STACK配列にはXMLの全エレメントの名前が格納されるので、カレントのエレメントを特定することに利用できるし(コールバック時)、XML_ELEMENT_DEPTHを調べればカレントXMLエレメントの階層を確認できるのだ。なおXML属性は、各属性別の明示的なコールバックで個別処理をするのではなく、すべての属性がパラメータ群に渡された上で、XMLエレメントのコールバックが開始されるようになっている。

 Expatコールバックのエントリポイントとしては、bashの関数群を利用するのが便利だろう。下記のサンプルコードは、ugu.xmlという簡単な構成のファイルを、BashDiffのexpatビルトインを用いて構文解析させるというものだ。ここでのstartelem関数の役割は、新規XMLエレメントの処理開始を行うことで、ノーマル版bashのdeclare関数を用いて、呼び出し時におけるXML_TAG_STACK配列の内容を表示させている。そしてこのサンプルコードでは、XML属性がどのように処理されているかを示すため、BashDiffによりstartelemに渡される2つ目のパラメータを出力させるようにしている。

$ cat ugu.xml
<ugu foo="bar" linux="fun">
 <nested one="two" three="four" />
</ugu>
$ startelem() {
  declare -p  XML_TAG_STACK;
  echo $2;
}
$ expat -s startelem ugu.xml
declare -a XML_TAG_STACK='([0]="ugu")'
foo=bar
declare -a XML_TAG_STACK='([0]="nested" [1]="ugu")'
one=two
最終更新:2009年01月05日 17:08