/Jan [0123][0-9]/
これは良くない。
「Jan 39」という存在しない日付にマッチしてしまうし、それ以上に問題なのが「Jan 7」という正しい日付にもマッチしない。
/Jan (0?[1-9]|[12][0-9]|3[01])/
これはどうか。
いっけん正しく見えるが、落とし穴がある。
「Jan 12」であるにもかかわらず、「Jan 1」でマッチ終了してしまうからである。
検証コード
<?php $str = 'Jan 12'; preg_match('/Jan (0?[1-9]|[12][0-9]|3[01])/', $str, $m); var_dump($m); array(2) { [0]=> string(5) "Jan 1" [1]=> string(1) "1" } ?>
丸かっこの中は左から順番に捜査され、最初にマッチするものを発見すると捜査を終了します。
※. ほとんどの正規表現エンジンはこの「順序付き選択」の挙動を持つが、すべてを捜査してから判定をくだす正規表現エンジンもあります。
/Jan ([12][0-9]|3[01]|0?[1-9])/
これが正解。
前例の正規表現の丸かっこの中の順番を入れ替えたものだ。
こうしておけば「Jan 12」にも正しくマッチする。
検証コード
<?php $str = 'Jan 12'; preg_match('/Jan ([12][0-9]|3[01]|0?[1-9])/', $str, $m); var_dump($m); array(2) { [0]=> string(6) "Jan 12" [1]=> string(2) "12" } ?>