Posted at

正規表現に出てくる"?:"について

phpの正規表現をみる中で「?:」という書き方の意味がわからなかったので調べました。

公式マニュアルのサブパターンに、下記のように記載があります。


開きカッコの後に "?:" を付けると、そのサブパターンは値のキャプチャを行わず、 キャプチャ用サブパターンの番号としてもカウントされません。

例えば、 文字列 "the white queen" に対し、次のパターンをマッチングさせてみましょう。


マニュアルにコード例が書いてあったものの、結果が載っていなかったので確認のために試してみました。

PHPをインタラクティブモードで実行して確認を行います。

$ php -a


?:をつけない場合

マニュアル通りの文字列とパターンでの実行結果です。

php > $text = 'the red king';

php > preg_match('/the ((red|white) (king|queen))/', $text, $m);
php > var_dump($m);
array(4) {
[0]=>
string(12) "the red king" // パターン全体にマッチした結果
[1]=>
string(8) "red king" // 外側の括弧にマッチした結果
[2]=>
string(3) "red" // 内側の1番目の括弧にマッチした結果
[3]=>
string(4) "king" // 内側の2番目の括弧にマッチした結果
}


?:をつける場合

こちらも同じくマニュアル通りです。

内側の1番目の開き括弧の後に "?:" を記載したため、こちらはキャプチャが行われておりません。

番号も0,1,2となっているため、下記の記述の通りになっているようです。


そのサブパターンは値のキャプチャを行わず、 キャプチャ用サブパターンの番号としてもカウントされません


php > $text = 'the red king';

php > preg_match('/the ((?:red|white) (king|queen))/', $text, $m2);
php > var_dump($m2);
array(3) {
[0]=>
string(12) "the red king" // パターン全体にマッチした結果
[1]=>
string(8) "red king" // 外側の括弧にマッチした結果
[2]=>
string(4) "king" // 内側の2番目の括弧にマッチした結果
}

もちろん内側の2つの括弧両方に"?:"を記載すると、両方ともキャプチャされなくなります。

php > preg_match('/the ((?:red|white) (?:king|queen))/', $text, $m3);

php > var_dump($m3);
array(2) {
[0]=>
string(12) "the red king"
[1]=>
string(8) "red king"
}