ぴよログ

↓に移転したのでこっちは更新されません、多分。

Rubyで文字列を正規表現にマッチする単位で分割する方法

移転しました →

タイトルがわかりづらいけど、この文字列を

str = "ab#cde#  ##...fgh.i##"

こうしたい、

["ab", "#", "cde", "#", " ", " ", "#", "#", ".", ".", ".", "fgh", ".", "i", "#", "#"]

という話。

文字列はひとまとめ、それ以外はバラバラにという感じで。

分割というとまずString#splitが思いつく。String#splitは普通に使うと区切り文字で分割した文字列の配列を返してくれる。そのため上のような結果が欲しい場合には使えない。区切り文字にした文字が消えてしまうからね。

ところでドキュメントを読んだらこんな風にかいてあった。

If pattern is a Regexp, str is divided where the pattern matches. Whenever the pattern matches a zero-length string, str is split into individual characters. If pattern contains groups, the respective matches will be returned in the array as well.

括弧によるグルーピングがあればマッチしたグループも結果の配列に入ってくれるらしい。これはいけるんじゃないか?と思ったので試してみた。

regexp = /([\w]+|#|\.| )/
str = "ab#cde#  ##...fgh.i##"
str.split(regexp)
# => ["", "ab", "", "#", "", "cde", "", "#", "", " ", "", " ", "", "#", "", "#", "", ".", "", ".", "", ".", "", "fgh", "", ".", "", "i", "", "#", "", "#"]

##...みたいな部分が分割されまくってて空文字列がたくさんはいっているけど、それを除くと欲しい単位で分割されているように見える。ここから空文字列を取り除く。

regexp = /([\w]+|#|\.| )/
str = "ab#cde#  ##...fgh.i##"
str.split(regexp).select {|s| !s.empty? }
# => ["ab", "#", "cde", "#", " ", " ", "#", "#", ".", ".", ".", "fgh", ".", "i", "#", "#"]

できた!