青木です。
In mail "[ruby-dev:23139] backslash in string"
Jun Adachi <adachi / jun.email.ne.jp> wrote:
> 安達@沖データと申します。
> (1) 無意味なバックスラッシュを入れると数が合わない?
>
> irb(main):010:0> " \ab\de\ff"
> => " \abde\ff"
>
> これって、" abdeff"か" \ab\de\ff"かのどちらかになって欲しい気がします。
> もちろんlengthで数えると長さは7です。
これは仕様通りです。\a と \f は正しいバックスラッシュ記法なので
それぞれベルと改ページに変換される。\d は正しくないので「d」
そのものになる。
> (2) gsubが正しく動いていない???
> irb(main):002:0> " \\ab\\de\\ff".gsub(/\\([a-f][a-f])/o, "\\1".to_i(16).chr)
> => " \000\000\000"
>
> これは、おかしい。
gsub は普通のメソッドですから、引数が gsub に渡るまえに
変形してしまっては意味がありません。"\\1".to_i(16) は 0 です。
ブロックのあり・なしだけだと「似たようなもん」だと思ってしまうん
ですが、実際のところ、ブロック付き gsub とブロックなし gsub は
別のメソッドと思ったほうがいいです。この違いにはまる人があまりに
多すぎる。
個人的には以下のように使い分けます。
* 固定文字列に置換するときは常にブロックなし sub / gsub
* 可変の文字列に置換するときは常にブロック付き sub / gsub
例えば gsub(/\s+/, "") みたいなのは常にブロックなし。
「\1」や「\&」が出てきそうになったら迷わずブロックを使う。
> irb(main):003:0> " \\ab\\de\\ff".gsub(/\\([a-f][a-f])/o) { | c |
> irb(main):004:1* c.to_i(16).chr
> irb(main):005:1> }
> => " \000\000\000"
>
> これも、おかしい。
c は $& 相当で、つまり「\ab」や「\de」です。
でもって "\\...".to_i は 0 なので、これで正しい結果です。
$1.to_i(16).chr なら予測通りになると思います。
-------------------------------------------------------------------
青木峰郎