rubyベストプラクティスChapter7.1
入力が色々なエンコーディングが想定される場合のライブラリ側の対応方法。例としてCSVライブラリを見ている。
CSVライブラリは読み込みのデータが大量であることが結構あるので、入力データのエンコーディングを変更するのではなく、パーサ側のエンコーディングを変えてるらしい。
本の中で上記のことを実現するために
def sjis_re(str) Regexp.new(str.encode("Shift_JIS")) end
ってメソッドを作っていて
"foo あ bar" =~ sjis_re("(\w+)\sあ\s(\w+)")
ってマッチを書いてるけどsjis_reに渡す時に「"」じゃ僕の環境ではマッチしなかった。
"foo あ bar" =~ sjis_re('(\w+)\sあ\s(\w+)')
ってするとマッチする。
これをcsvライブラリでは汎用的にしていてそれらが、escape_reとencode_reメソッドになる。
def escape_re(str) str.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join end def encode_re(*chunks) Regexp.new(encode_str(*chunks)) end
で、@re_charsと@re_escってのは
@re_esc = "\\".encode(@encoding) rescue "" @re_chars = %w[ \\ . [ ] - ^ $ ? * + { } ( ) | # \ \r \n \t \f \v ]. map { |s| s.encode(@encoding) rescue nil }.compact
っていう風に設定されている。
よくわからんので、これらをirbでためしてみると
ruby1.9.2@180 > re_esc = "\\".encode(@encoding) ruby1.9.2@180 > re_chars = %w[ \\ . [ ] - ^ $ ? * + { } ( ) | \ \r \n \t \f \v ] ruby1.9.2@180 > 'hoge'.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join > hoge ruby1.9.2@180 > 'ho\ge'.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join > ho\\\\ge ruby1.9.2@180 > Regexp.new('ho\ge'.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join) > /ho\\ge/
ってなる。
本にも書いてある通り、正規表現上でのクオートしなきゃいけない文字列を適切にクオートしてくれるらしい。
ここでは、csvのような様々な文字コードの入出力を意識しなきゃいけないって時には内部のコードを入出力の文字コードにあわせるといいよってことだと思う。
Rubyベストプラクティス -プロフェッショナルによるコードとテクニック
- 作者: Gregory Brown,高橋征義,笹井崇司
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/03/26
- メディア: 大型本
- 購入: 9人 クリック: 307回
- この商品を含むブログ (43件) を見る