JISコードの文字数を調べる(2)
修正版
エスケープシーケンスチェックあたりのロジックミスがあったので修正した版。
その他、ループ部分やエスケープシーケンス部分のチェックの記述方法を変更した。
def jis_couner(str) esc_flag = false esc_string = "" wide_byte_flag = false wide_first_byte_flag = false count = 0 # JIS での文字数カウント # 文字数カウント処理(バイトの配列にしてループさせる) str.to_s.unpack('C*').each_index do |index| # 改行コードは除外 next if str[index] == 0x0a # 2バイト文字フラグがあって、1バイト目を通過している場合 if wide_byte_flag && wide_first_byte_flag && (str[index].to_i >= 0x21 && str[index].to_i <= 0x7E) count += 1 wide_first_byte_flag = false elsif wide_byte_flag && (str[index].to_i >= 0x21 && str[index].to_i <= 0x7E) # 2バイト文字フラグがあって、1バイト目を通過していない場合 wide_first_byte_flag = true # 1byte 目通過フラグ on else count += 1 end # エスケープシーケンスチェック if str[index] == 0x1b or esc_flag esc_flag = true esc_string << str[index] # 2バイト文字カウントフラグを off wide_byte_flag = false end # エスケープシーケンスが3文字に達した時点で評価する if esc_string.size == 3 # エスケープ文字列かチェックする # 1バイト文字 if esc_string =~ /(\x1b\x28\x42)|(\x1b\x28\x4A)|(\x1b\x28\x49)/ # 2バイト文字カウントフラグを off wide_byte_flag = false # 制御コード分の文字数をマイナスする count -= 3 elsif esc_string =~ /(\x1b\x24\x40)|(\x1b\x24\x42)|(\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"))