ついカッとなって
2008/08/22:修正版→JISコードの文字数を調べる(2) - @sugamasao.blog.title # => ”コードで世界を変えたい”
文字数を調べるプログラムを作ってしまった。
ちなみに、 SJIS ではなく、 JIS のコードである。
JISコードは1バイト文字や2バイト文字の開始時にエスケープシーケンスとして、制御コードが3バイトはいるので単純にバイトで区切るとたいへんな事になる。
なので、無理くり作ってみた。こ汚いソースだけど、ブラッシュアップの前に、とりあえず動くソースということで。
ちなみに、作成にあたり、ここのエスケープシーケンスの表を握りしめながらやった。
http://ash.jp/code/code.htm
ソース
def jis_couner(str) esc_flag = false esc_string = "" wide_byte_flag = false wide_first_byte_flag = false count = 0 # JIS での文字数カウント1 # 文字数カウント処理 str.each_byte do |s| # 改行コードは除外 next if s == 0x0a # 2バイト文字フラグがあって、1バイト目を通過している場合 if wide_byte_flag && wide_first_byte_flag && (s >= 0x21 && s <= 0x7E) count += 1 wide_first_byte_flag = false elsif wide_byte_flag && (s >= 0x21 && s <= 0x7E) # 2バイト文字フラグがあって、1バイト目お通過いていない場合 wide_first_byte_flag = true # 1byte 目通過フラグ on else count += 1 end # エスケープシーケンスチェック if s == 0x1b or esc_flag esc_flag = true esc_string << s end # エスケープシーケンスが3文字に達した時点で評価する if esc_string.size == 3 # エスケープ文字列かチェックする # if:1バイト文字 elsif 2バイト文字 if esc_string =~ /(\x1b\x28\x42)/ or esc_string =~ /(\x1b\x28\x4A)/ or esc_string =~ /(\x1b\x28\x49)/ # 2バイト文字カウントフラグを off wide_byte_flag = false # 制御コード分の文字数をマイナスする count -= 3 elsif esc_string =~ /(\x1b\x24\x40)/ or esc_string =~ /(\x1b\x24\x42)/ or esc_string =~ /(\x1b\x24\x44)/ # 2バイト文字カウントフラグを on wide_byte_flag = true # 制御コード分の文字数をマイナスする count -= 3 end # 初期化 esc_string = "" esc_flag = false end end return count end # テストプログラム file = [] File.open('./text.txt').each do |f| file << f end puts jis_couner(file.join('\n'))
ファイル内容
JISコードで以下のように書いてあるファイルをテストとして用意した
あいうえお12345
12345カキクケコ
実行結果
sugamasao% ruby ./char_count.rb
20
とりあえず、それっぽくカウントできているようだ。
っていうか、 JIS コードには制御コードがあって、それを使って1バイト文字と2バイト文字をチェックしているなんて、いままで知らなかったよ。。。