正規表現ってあるじゃないですか。そうです。アレです。

とっても便利で、いろんな場面で役立つと思うんですが、ときどき最短マッチを使いたくなって「最短マッチってどう書くんだっけなぁ?」ってなってググることがあります(よね!)

通常は最長マッチになる

通常、正規表現内で * とか + とか付けると、直前の表現の0回/1回以上の繰り返しを表しますが、この書き方だとできるだけ長い要素にマッチしようとします。大事なことなのでもう一度言います。できるだけ長い要素にマッチしようとするんです。

大抵はそれで構わないんですが、ときどきそれでは困るケースがあります。例えばこんなケースを考えてみましょう(あんまり良い例が思いつかない)。

・"名前(ニックネーム)"という形式
・名前と(ニックネーム)の間には半角or全角スペースがあったりもする

このような場合、正規表現はおそらくこのような形になるでしょう。

def split_name(name)
  if name =~ /^(.+)[\s ]?((.+))$/
    [$1, $2]
  end
end

# (a)
name_str = "佐々木達也(ささたつ)"
p split_name(name_str) # ["佐々木達也", "ささたつ"]

# (b)
name_str = "佐々木達也 (ささたつ)"
p split_name(name_str) # ["佐々木達也 ", "ささたつ"]

$1に名前が、$2にニックネームが入りますよね。(a) の場合は何も問題ありません。ただ困ってしまうのが、名前と(ニックネーム)の間に半角or全角スペースが入っている (b) のような場合です。

半角or全角スペースはあったり無かったりなので [\s ]? としていますが、その前の (.+) ができるだけ長くマッチしようとするため、(b) の場合には半角or全角スペースの部分までマッチしてしまいます。。

* とか + の後ろに ? を付けると最短マッチに

そんなときには最短マッチを使うと便利です。今まで * とか + とか書いていたのを *? とか +? とか書くだけです。これだけで最短マッチになります!

def split_name(name)
  if name =~ /^(.+?)[\s ]?((.+))$/ # ? を追加
    [$1, $2]
  end
end

# (a)
name_str = "佐々木達也(ささたつ)"
p split_name(name_str) # ["佐々木達也", "ささたつ"]

# (b)
name_str = "佐々木達也 (ささたつ)"
p split_name(name_str) # ["佐々木達也", "ささたつ"]

(b) の場合にも、余計な半角or全角スペースを含まずに抽出することが出来ました。なるべく短くマッチしようとするため、半角or全角スペースの部分は [\s ]? がマッチするわけですー。

参考:正規表現 - Rubyリファレンスマニュアル
このエントリーをはてなブックマークに追加