From: Wakou Aoyama Date: 2001-12-18T13:51:12+09:00 Subject: [ruby-dev:15487] Re: gsub weirdness: gsub(/.*$/, "foo") 青山です。 On Mon, Dec 17, 2001 at 12:54:27PM +0900, Akinori MUSHA wrote: > % ruby -e 'p "aab".scan(/a*b/)' > ["aab"] > % ruby -e 'p "aa\n".scan(/a*$/)' > ["aa", ""] > > というのはあまりうれしくないなと。 私もその気持はわかります。しかし、それを解決するには、* と (?=) が問題 であって、$ つまり、行末の概念というか、定義の問題ではありません。 $ ruby -e 'p "aab".scan(/a*(?=b)/)' ["aa", ""] 1つは、* は空にもマッチするので、ちょっと予想外の所にマッチするという 問題ですね。これは、詳説正規表現に書いてある例です。 $ ruby -e "p 'a 1234 num'.index(/[0-9]*/)" 0 $ ruby -e "p 'a 1234 num'.index(/[0-9]+/)" 2 * の場合は、空にもマッチするので、1234 の部分ではなく、最初の空にマッ チするので、index 0 となるわけです。 この挙動をどうみるか、という点と、 >  例えば、「gsub()/scan() など連続マッチのとき、 i..j の直後の > j..j は除外する」という仕様もありえると思いました。つまり現状: これが先の例の違いである、b と (?=b) の違い、すなわち、(?=) はマッチ位 置を先に進めるか、という問題ですが、これを進めるようにしてしまうと、問 題がおこる場合もあります。 $ ruby -e 'p "ababab".scan(/a(?=b)|b(?=a)/)' ["a", "b", "a", "b", "a"] ちょっといいかげんな例ですが、これで、もし、j..j を除外する、すなわち、 (?=) のマッチで、直前からカーソルを移動すると、おそらく、a(?=b) にマッ チした直後の b(?=a) はマッチしなくなり、b(?=a) の直後の a(?=b) はマッ チしない、という動きになるように予測されます。 従って、簡単には捨てたり進めたり、という解決はできず、挙動を変えるには、 かなり難しい議論が必要になってくると思われます。 という事で、 >  最後の \n の特別扱いという点では、 > > % ruby -e 'p "\n\n".scan(/\n*$/)' > ["\n", ""] > > という結果が特徴的ですね。上記のもろもろを踏まえていないとかなり > 悩むに違いない。そして「直後の空」はやはり奇妙。 これもやはり、\n の特別扱いや、直後の空、というより、(?=) の直前の * の問題というか、特徴というか、そういう事の1つでしょうね。 この挙動をご提案の挙動にできれば、私もわかりやすくて良いとは感じますが、 詳説正規表現のコラムに、そういうものだ、という感じで書かれているぐらい ですから、改善というか、変更はかなり困難なのではないかな、と予測します。 -- 青山 和光 Wakou Aoyama