[PHP-users 31851] Re: 検索結果を第3引数に代入する時のpreg_match()の挙動について
lange @ e-mail.jp
lange @ e-mail.jp
2007年 4月 7日 (土) 15:48:53 JST
tuchidaです。
長谷部さま
> この場合、$matches[1]と$matches[3]には空文字列が入るだろうと期待していたのに、
> 実際には$matches[1]に空文字列が入り、$matches[3]には値がセットされませんでした。
>
> これはバグでしょうか。それとも仕様でしょうか。
仕様だと思います。正規表現部位だけを抽出しますが。
'/^(string)?;(string)?;(string)?$/'
とは
'/^(?:(string)|);(?:(string)|);(?:(string)|)$/'
に置き換えられると思います。(要はサブパターンとマッチする
か、「何ともマッチしないか」という事です。ゆえにご希望の動
作を実現する為には ? を使わず
'/^(string|);(string|);(string|)$/'
とすれば動作するかと思います。(php4.4.4では確認)
しかし、サブパターンが失敗しているのに(preg_matchに
PREG_OFFSET_CAPTUREをつけて$matchesをvar_dumpすれば確認でき
ると思います)値が入ってしまっているのは、マッチした変数
の入る順番が「空の場合は無視する」ように*詰める処理*を行っ
てしまうと、次のようなプログラムの場合
(例:恥ずかしい例なのでツッコミはご容赦...
if( preg_match( "#http(s)?://(.*)#", $url, $matches (
{
// $matches[1] を使って https か http かを判断
}
$matches[1]には (.*) のデータが入るか (s) のデータが
入るかを判断し辛いからだと推測します。
php 4.4.4の ext/pcre/php_pcre.c:529行目- にも
/*
* If the number of captured subpatterns on this run is
* less than the total possible number, pad the result
* arrays with empty strings.
*/
if (count < num_subpats) {
for (; i < num_subpats; i++) {
add_next_index_string(match_sets[i], empty_string, 1);
}
}
とか書いてあるので、ここらへんなのかなーとか思ってます。
(C言語は素人なので、オオボケかもしれません...)
[テスト環境]
Windows XP
PHP 5.2.1
TurboLinux 10
PHP 4.4.4
tuchida <lange @ e-mail.jp>
http://bp2.jp/
PHP-users メーリングリストの案内