IIJ さんが開発している mruby 向けの正規表現ライブラリ iij/mruby-regexp-pcre を使ってたら、本家 CRuby と違う挙動の部分を見つけました。
# 文字列の先頭に空白が含まれている場合、それを取り除く。
"foo".gsub /^\s*/, ""
上の "foo"
の場合では、先頭に空白は含まれていないので、そのままの文字列 "foo"
が返ってくるはずです。 iij/mruby-regexp-pcre を使うと、これが空の文字列 ""
として返ってきてました。 CRuby1.9.3 でチェックしてみたところ、"foo"
が返ってきています。
最初は mruby の String#gsub
の問題かなと思って mruby/mruby のコードを追っていましたが該当箇所が見つかりません。よく考えてみたら、正規表現ライブラリは mruby の基本実装には組み込まれていないはずなので mruby/mruby に問題箇所があるわけがありませんね。2013年の下記の issue を見てみても、「正規表現ライブラリはちゃんと切り分けて、String#gsub
なんかの挙動は拡張側で適宜上書きしようぜ!」という流れが見てとれました。(英語苦手だけど)
Library independent RegExp ・ Issue #841 ・ mruby/mruby
また、一瞬だけ本家 CRuby で使用している正規表現ライブラリは鬼車であって、mruby-regexp-pcre は PCRE である違いも考えましたが、
"foo".gsub /^\s*/, ""
で空文字が返ってくるのは、そもそも使用しているライブラリ以前の問題のような気がしました。
ということで、iij/mruby-regexp-pcre の該当コードを読んでいると String#gsub
を上書きしているコードがありました。 対象部分をデバッガで追ってみると、位置指定子(^
)があるにも関わらず、1文字ずつ正規表現マッチ→マッチしたインデックスだけを用いて(空文字で)置換→元文字列がなくなるまでくりかえし、という挙動をしていたため、恐る恐る issue を投げてみました。 (颯爽と手直ししてプルリクできるくらいの能力がどこかに落ちてないでしょうか!)
2015/12/7 追記
レポートしておいた部分をしっかり修正していただけました!感謝多謝です。