2012年3月29日

[ruby-list:48670] Re: "a_b$c" を "a\_b\$c" に変換したいのですが、、、

okkez さん,信岡さん ありがとうございます
>
> どうすればよいかは okkez さんが示されていますが、なぜそうなるのか
> 簡単に説明を。
>
> String#gsub の第 2 引数では、「\&」 でマッチした文字列を表したり
> 「\1」 で最初のキャプチャ文字列を表したりできるわけで、バックスラッシュに
> 特別な意味があります。 そのため、単なるバックスラッシュを表したい場合には

> バックスラッシュを 2 つ連続させる必要があります。

これは知っていたので、 \\ で \ に、 \& でマッチ部分に、
ということで行けるかと思ったのですが、\ 5つですか。

 (1)ソース上の '\\\\\\&' が読み込まれて '\\\\&' になり
 (2)コンパイルのときに '\\&' になって
 (3)gsub 実行時に \\ が \ に & がマッチ部分に

ということなのかな。
(2)のステップをイメージしていませんでした。一つ利口になれました。
ありがとうございます。

あれ、、、違うみたいだな、
puts "a_b$c".gsub(/[_$]/, '\\ \&') 

puts "a_b$c".gsub(/[_$]/, '\&\\')
だと \\ で \ になる。
やはり \ は難しい。わからん。

> (ただし、バックスラッシュと後ろの文字の組み合わせが特に意味を
> もたない場合は、単一のバックスラッシュでもバックスラッシュと
> して認識されるみたいです。)

これはマニュアル通りですね。
シングルクォートで囲まれた文字列では、 \\ (バックスラッシュそのもの)
と \' (シングルクォート) を除いて文字列の中身の解釈は行われません。

gsub をブロックで受ける方法は再認識しました。
これもマニュアルでは目に入ってましたが素通りでした。
ややこしくなったらこれを使うことが良さそうですね。
ありがとうございます。

############
PS
シングルクォートに囲まれた連続する \ の扱いが、単なる文字リテラル
ではマニュアル通りですが、sub,gsub の replace ではおかしくなって
居る様です。
irbだとreadlineでのエスケープ処理が絡んでくる恐れも
あるか、とfileにして実行してみました。ruby 1.9.3p125です

puts"a_b$c".gsub(/[_$]/,'\\\\\\&') # 8 => a\_b\$c
puts"a_b$c".gsub(/[_$]/,'\\\\\&') # 9 => a\_b\$c
puts"a_b$c".gsub(/[_$]/,'\\\\&') #10 => a\&b\&c
puts"a_b$c".gsub(/[_$]/,'\\\&') #11 => a\&b\&c
puts"a_b$c".gsub(/[_$]/,'\\&') #12 => a_b$c

puts"a_b$c".gsub(/[_$]/,"\\\\ \&") #13 => a\ &b\ &c
puts"a_b$c".gsub(/[_$]/,"\\\ \&") #14 => a\ &b\ &c
puts"a_b$c".gsub(/[_$]/,"\\ \&") #15 => a\ &b\ &c
puts"a_b$c".gsub(/[_$]/,"\ \&") #16 => a &b &c

puts"a_b$c".gsub(/[_$]/,'\\\\ \&') #17 => a\ _b\ $c
puts"a_b$c".gsub(/[_$]/,'\\\ \&') #18 => a\ _b\ $c
puts"a_b$c".gsub(/[_$]/,'\\ \&') #19 => a\ _b\ $c
puts"a_b$c".gsub(/[_$]/,'\ \&') #20 => a\ _b\ $c

マニュアルには
シングルクォートで囲まれた文字列では、 \\ (バックスラッシュそのもの)と
\' (シングルクォート) を除いて文字列の中身の解釈は行われません。

とありますが、その通りになっていないように思われます。
puts '\\\\\\\\' などような単純な文字リテラルの時は 
\\ => \ の期待通りになっていますが、
sub や gsub の replace の時の扱いがおかしいです。
puts"a_b$c".gsub(/[_$]/,'\\\ ') # => (1)a\ b\ c
puts"a_b$c".gsub(/[_$]/,'\\\\') # => (2)a\b\c
puts"a_b$c".gsub(/[_$]/,'\\\\\ ') # => (3)a\\ b\\ c
puts"a_b$c".gsub(/[_$]/,'\\\\\\') # => (4)a\\b\\c
puts"a_b$c".gsub(/[_$]/,'\\\\\\ ')# => (5)a\\ b\\ c

マニュアル通りなら各々下の様になるのでは?
a\\ b\\ c、a\\b\\c、a\\\ b\\\ c、a\\\b\\\c、a\\\ b\\\ c

投稿者 xml-rpc : 2012年3月29日 09:22
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/109220
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。