[ruby-list:48670] Re: "a_b$c" を "a\_b\$c" に変換したいのですが、、、
From:
dezawa <dezawa@...>
Date:
2012-03-29 00:22:06 UTC
List:
ruby-list #48670
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