館林です。

 Shin-ichiro Hara <sinara / blade.nagaokaut.ac.jp> さんが
                2000/02/08 午後 12:31:29に書いた
 「[ruby-list:20580] Re: エスケープされていないものだけを置換」 のお返事です:

> 原です。
> 
> |ごとけんです
> 
> |適用範囲によりますが、これだと先頭の _ は置換できないので、
> |次のようにした方が安全かも知れません。
> |
> |a.gsub(/(^|[^\\])_/, '\1 ')
> 
> これが正解と思いますが、もしかして \ で \ をエスケープ可能に
> してたりしません? a = "\\\\_" の場合とか。だとすると実直に
> 
>   a.gsub(/\\?[\\_]/) { case $& when "_" then " " else $& end }
> 
> とかしたほうがいいかもしれません。

 ありがとうございます。\\\\は考えていませんでした。たしかに
ありえます。
 使わせていただいたところ、"_abc\\\\_d\\_e"もちゃんと、
" abc\\\\ d\\_e"と置換されました。

 すごいです。質問してから、24時間たらずでいくつもの新しい発見
がありました。

 僕の質問に答えていただいた皆さん、ありがとうございます。
 以下、FAQっぽい物をつけてみます。
 教えていただいた内容を適宜編集させていただいています。

Q.エスケープされていない文字だけを置換したいのです。
具体的には、_を空白に置換したいのですが、\_は置換したくないのです。
どうしたら良いのでしょうか?

A.

a = "_ab_c\\_d"
a.gsub(/[^\\][_]/," ")
だと、
"_a c\\_d"
とbまで消えてしまいますし、行頭の_も置換されません。
 gsubは、以降のブロックで、$1という後方参照が利用できます。

a.gsub(/([^\\])[_]/){$1+" "}

"_ab c\\_d"

これを実行すれば、bは消えなくなりました。
でも、これよりも、

gsub(/([^\\])_/, '\1 ')

こっちのほうが、すっきりしているでしょう。
但し、行頭の '_' はまだ置換されません。

a.gsub(/(^|[^\\])_/, '\1 ')

" ab c\\_d"

と、これで、無事、行頭の'_'も置換できました。

 しかし、 \ で \ をエスケープ可能にしてある場合は、
  a = "\\\\_" # この場合、\\は_にかからない。
  a.gsub(/\\?[\\_]/) { case $& when "_" then " " else $& end }
  p a
"\\\\ "
とかしたほうがいいかもしれません。

ちなみに、Perlだと、
$a = "_abc_d\\_e_";
$a =~ s/(^|[^\\])_/\1 /g;
$a =~ s/(?<!\\)_/\1 /g;      #5.005以降
$a =~ s/(\G|[^\\])_/\1 /g;   #5.005以降
なんて書けます。

■参考URL
Mastering Regular Expressions 
http://public.yahoo.com/~jfriedl/regex/
詳説正規表現 
http://www.oreilly.co.jp/BOOK/regex.htm
 「詳説正規表現」読書メモ (by なひ)
 http://www.jin.gr.jp/~nahi/src/mre.html
正規表現メーリングリスト
http://www.bug.org/ML/regexp/
正規表現メモ
http://www.kt.rim.or.jp/%7ekbk/regex/regex.html


========================================================
   綾乃介@IBARAKI Univ.
      E-mail: aya / big.or.jp
      URL:http://www5.big.or.jp/~aya/
========================================================
茨城県日立市の総合情報サイト
    メディアネットワーク マンボウ WebSite
                http://manbow.cgi-space.to/
========================================================