Rubyでwc

今日は,仕事が一段落したという事で,久しぶりにRubyのお勉強もといコードリーディング.今回は,Rubyあれこれの,wc.rbを読んでみました.トイレという訳ではなく,linuxのコマンドの一つ,wc(たぶん,word countの事)をRubyで実装.※wc.rbを読んだ事を前提に書いてます.


ただコピペするだけでなく,実際にコーディングしながらirbで動作確認というスタイルでいつもやっていますが,今回は一部を除いて動作確認するほどではありませんでした.その一部というのが,


while gets(nil)
filename = ARGF.filename # ARGFってのも違和感ある...オブジェクト指向ならではだなぁ

line_count = $_.count("?n") if opt_line
char_count = $_.size if opt_char
word_count = $_.word_size if opt_word

ここ.やはりC言語育ちな僕に取って,ファイルもオープンせずに,どうやって文字数や単語数,行数を数えているのか,サッパリでした.結局,タネはgets(nil)にアリ.irbにて検証.

irb(main):001:0> ARGV.push "wc.rb"
=> ["wc.rb"]
irb(main):002:0> gets(nil)
=> "RCS_ID = '$ID: wc.rb,v 1.7 2002/04/25 $'¥n# usage:¥n¥nclass
String¥n¥tdef word_size¥n¥t¥tself.scan(/¥¥S+/).size¥n¥tend¥nend
¥n¥ndef usage¥n¥tSTDERR.print ¥"usage: ¥#{$0} [-l
...(略
どーゆー仕組みだかわかんないけども,ARGVがファイル名の時,gets(nil)でそれを読み込むみたい.ほんとどーゆー仕組みなんだろう.んで,結局getsで読み込まれたファイルはデフォルトの$_に入って,以降の処理をするんだな.いやーよく出来てる.

良く出来てるんだけど,一ヶ所バグが.それは,wc.rbに何も引数を渡さなかった時,usageが出ないんだな.なんとケアレスミスか.修正方法は簡単すぎるので載せません.


ついでに.どーせオリジナルのwcなんだから,カッコ良くしたい.そこで,以下の行を変更,追加.何処を変更,何処に追加かは,感じてください.


printf(" line |") if opt_line
printf(" word |") if opt_word
printf(" char |") if opt_char
printf(" filename")
puts # 仕切りを付ける

printf("--------+") if opt_line
printf("--------+") if opt_word
printf("--------+") if opt_char
printf("---------")
puts # もういっちょ仕切り

printf("%8d|", line_count) if opt_line
printf("%8d|", word_count) if opt_word
printf("%8d|", char_count) if opt_char
printf(" %8s", filename) if filename != '-'
puts # 懲りずに仕切り

if n_arg > 1
printf('%8d|', line_total) if opt_line
printf('%8d|', word_total) if opt_word
printf('%8d|', char_total) if opt_char
puts " total" # 最後も仕切り
end

これで,ちょっとSQLっぽくなります:-)オプションでSELECTしてる気分.


余談ですが,今回この記事を書いてて面倒くさいと思ったのが,ソースをコピペすると,¥が文字化けして?になっちゃうって点.わざわざ全角に書き換えないといけない.いちいちsedに掛けるのも面倒くさいし,折角だからRubyで簡単なスクリプト書いちゃうか.