last update: 2013/09/03

2007/07/12

今日のお仕事

土曜日の昼過ぎに飛行機で北海道から福岡に飛ぶんですけど、ちょうど同じ時間帯に台風が沖縄から九州に飛んできてくれるらしいです。ぽわわツアーズ危うし。

セットアッププログラムを作ってる関係で、なんかリビジョン管理の仕事もあったりします。で、テスト中のバイナリのリビジョンを明確化するためにセットアップにリビジョンを刻んだファイルを同梱することに決定したのが昨日で、実際にテスト用パッケージ作るのが明日。

さてさて、リビジョンはsvnからとってくるとして、いちいち自分でsvnコマンド叩いてリビジョン調べてそれを書き写す…なんてするわけねーよ! 面倒とかそれ以前に、人間がやるとミスるのでそういうのは自動化して管理しないとね。

ってことで、バージョンとリビジョンを刻んだファイルをこんな感じにしようと考えたんです。

Name: (製品名) Ver 1.0
Revision: (リビジョン)
Date:  (年月日)

というわけで、これを自動的に生成するのが今日のミッションだー。

といってもこんなのはシェルスクリプトを使えば楽勝です。svn infoをチェックアウトしたトップのディレクトリに対して実行すればリビジョンと最終更新日時を拾えますから。svn infoの出力はこんな感じ。

kawazoel@debian:~/svntest$ svn info
Path: .
URL: file:///home/repository/beatsync/webout/trunk
Repository Root: file:///home/repository/beatsync
Repository UUID: 80da241c-e1fb-0310-a700-dfff8f974cbb
Revision: 55
Node Kind: directory
Schedule: normal
Last Changed Author: kawazoel
Last Changed Rev: 44
Last Changed Date: 2007-01-01 19:32:09 +0900 (Mon, 01 Jan 2007)

この強調部分からさっきのテキストを作るわけですが、1行目は常時固定で、管理しなきゃならないのは2行目のリビジョン番号と、3行目の更新日時。

この辺はまぁLinuxのシェルスクリプトなら習作レベルですよね。こんな感じで作りました。

svn info . | grep Revision >> version.txt
svn info . | grep "Last Changed Date" | cut -c 14- >> version.txt

とまぁここまではよかったんだ! 問題はWindowsです。Windowsにはgrepもcutもないからなー。かなり困りました。っていうか、ボクのコマンド文化はUNIX系しかないので、Windowsのコマンドプロンプトとか貧弱すぎるイメージしかなくて文字列処理なんかやったことねーよ。

とりあえず、grepの代わりはfindコマンド(正規表現とかのパワフルな機能が欲しければfindstrコマンド)を使えばよいというのはわかったんですが、Last Changed Dateのところから前の13文字ぐらいをちょん切る(Linuxだとcut)コマンドがわかんねー。

で、結論からいうと、そんなのは、ない。

となれば、代替手段を考えるしかないわけですが、cmd.exeにはforという繰り返し処理用コマンドがあるんです。今日の伏兵はコイツだ!

for /?すればわかるんですが、forは基本的にファイルから1行読んできてそれを1行ごとになんか処理するのに使います。その処理の中で/Fオプションというのがあって、そいつがなかなか強力。

どう強力かというと、なんとデリミタ指定して任意の番目のフィールドを扱ったりできるようです。Linuxのcutコマンドでも、-dでデリミタ指定して任意のフィールドを切り出すっていうのがありますよね。アレみたいな感じなので、これはいけるぞと確信しました。

そうなれば、Last Changed Date: (略)のDate以下を取り出せばいいので、スペース区切りでトークン解析して、1番目(Last)と2番目(Changed)のトークンを削除しちゃえばOK! で、さらに/Fオプションのusebackqパラメータを使うとin節でファイル指定の代わりにバッククォートでくくった文字列をコマンド実行してくれちゃいます。こ、これだー。

というわけで、Linuxではgrepとcutを使ってた処理をWindowsのコマンドで書き直すとこうなりました。

svn info . | find "Revision" >> version.txt
svn info . | for /F "usebackq token=3*" %i in (`find "Last Changed Date"`) do @echo %i %j >> version.txt

いやー、LinuxとWindowsで同じ出力を得るためにここまで手法が変わるなんてなかなか面白いですね。forコマンドの%iとか%jについて解説しておくと、"token=3*"とすることで、in節の前の%iが3番目のトークン(Date:)、に割りあたります。

で、*は4番目以降のトークン全部っていう意味になって、iの次のjがその4番目以降トークンになるので、do節の@echo以下で %iと%jを出力すれば結果的に"Last Changed "という文字列の省かれた出力を得ることができるというわけでしたー。あーWindowsでのテキスト処理ってむずかしっ。

ともあれ、同じテキスト処理をしたくても処理系が変わるとこんなにも手法が変わってしまうのですよーというお話でしたー。アレゲな人には結構おもしろそうな話だと思うんだけど、想定している読者がすごくニッチになっているのは否めない…。

comments powered by Disqus