̃Gg[͂ĂȃubN}[Nɒlj

PHP :: 正規表現 / 「順序付き選択」を利用した例



「Jan 31 」という日付をマッチさせる場合を考える

/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"
}
?>



programming/php/regex/order_selection.txt