Just do IT

思うは招く

Ruby String#scan と String#split の違い

結論

  • scanは、マッチした文字列の配列を返す
  • splitは、マッチした部分で分割した配列を返す
    • 区切り文字を指定する

scanの挙動

サンプルとして以下のような文字列を用意する。

str = 'Now I need a drink, alcoholic of course, after the heavy
 lectures involving quantum mechanics.'

scanの場合。Rubyリファレンスには、「マッチした部分文字列の配列を返します。」と記述されている。

str.scan(/\w/)
=> ["N", "o", "w", "I", "n", "e", "e", "d", "a", "d", "r", "i", "n", "k", "a", "l", "c", "o", "h", "o", "l", "i", "c", "o", "f", "c", "o", "u", "r", "s", "e", "a", "f", "t", "e", "r", "t", "h", "e", "h", "e", "a", "v", "y", "l", "e", "c", "t", "u", "r", "e", "s", "i", "n", "v", "o", "l", "v", "i", "n", "g", "q", "u", "a", "n", "t", "u", "m", "m", "e", "c", "h", "a", "n", "i", "c", "s"]

\wとは、アルファベット、アンダーバー、数字のいずれかの正規表現[a-zA-Z_0-9]が相当する。つまりこれは、[a-zA-Z_0-9]のいずれかに相当する文字と合致したものを取り出して配列にしている。

まさに「マッチした部分文字列の配列」を返している。

ちなみに、\w\w+に変えると次のようになる。

str.scan(/\w+/)
=> ["Now", "I", "need", "a", "drink", "alcoholic", "of", "course", "after", "the", "heavy", "lectures", "involving", "quantum", "mechanics"]

+は「直前のパターンを 1 回以上繰り返す」という意味がある。結果的に、スペースで区切った各単語が配列になり返ってくる。

String#scan (Ruby 3.0.0 リファレンスマニュアル)

splitの挙動

対してsplitは、

  • 正規表現にマッチする部分で分割する。
  • その文字列自体にマッチする部分で分割する。

split(" ")(引数にはスペースを入れている)と記述し、スペースで区切ってみると・・・。

str.split(" ")
=> ["Now", "I", "need", "a", "drink,", "alcoholic", "of", "course,", "after", "the", "heavy", "lectures", "involving", "quantum", "mechanics."]

スペースで各単語を区切っている。str.scan(/\w+/)と違うのは、最後の文字列"mechanics."にカンマも含まれている点。

これはただスペースで区切っているだけなので、カンマが含まれる。

String#split (Ruby 3.0.0 リファレンスマニュアル)