Ruby の inspect
メソッドは Encoding.default_external の影響を受けるようだ。
まず,String オブジェクトがどんなバイト列になっているのかを調べるメソッドを定義しておく。
class String
def byte_sequence
bytes.map{|b| "%0X" % b}.join(" ")
end
end
そのうえで,default_external
を変えて文字列「あ
」を inspect
してみる。
Encoding.default_external = "UTF-8"
puts "あ".inspect.byte_sequence
#=> 22 E3 81 82 22
Encoding.default_external = "CP932"
puts "あ".inspect.byte_sequence
#=> 22 5C 75 33 30 34 32 22
それぞれの先頭と末尾にある 0x22 はダブルクオート "
だ。
UTF-8 版で,ダブルクオートに囲まれた E3 81 82
は UTF-8 での あ
のバイト列だ。
一方,CP932(いわゆる Windows 版 Shift JIS;「Windows 31J」ともいう)のほうは,\u3042
の形になっている。
そういえば,確かに
p "あ"
とやったとき,UTF-8 だと「"あ"
」と表示されるが,CP932 だと「"\u3042"
」と表示されたりするよな。
inspect
が p
メソッドのためにある,と考えればこの仕様は理解できなくもない。
でも,こんな大事なことがリファレンスマニュアル
http://docs.ruby-lang.org/ja/2.3.0/method/Object/i/inspect.html
http://docs.ruby-lang.org/ja/2.3.0/method/String/i/inspect.html
http://docs.ruby-lang.org/ja/2.0.0/method/Regexp/i/inspect.html
のどこにも書いてない。
で,だ。inspect
をデバッグなんか以外の目的で使いたいこともある。
今回のことに気づいたのも,ユーザーが入力した正規表現を HTML 形式のレポートの中に表示しようとして,Regexp#to_s
だとイマイチなので Regexp#inspect
にしたわけなのだが,日本語が混じってたときに \u3042
みたいになってて「あれ?」と思ったんだ。