PHPのpreg_matchで正規表現による文字列のパースをしようと思っております。
しかし、例えば以下のように内部オプションのJ (PCRE_INFO_JCHANGED)
を利用し、名前付きサブパターンでhost
の値を切り替えて取得ようとした際、マッチする・しないにかかわらず、最後に出現したhost
の結果で上書きされてしまいます。
lang
1$regex = '(?J)//(?:(?P<host>a[^?]*)|(?P<host>b[^?]*))?(?P<query>?.*)?'; 2$uri = '//aaabbb?hoge'; 3 4preg_match('`' . $regex . '`i', $uri, $matches, PREG_OFFSET_CAPTURE); 5var_dump($matches);
array (size=6) 0 => array (size=2) 0 => string '//aaabbb?hoge' (length=13) 1 => int 0 'host' => array (size=2) 0 => string '' (length=0) 1 => int -1 1 => array (size=2) 0 => string 'aaabbb' (length=6) 1 => int 2 2 => array (size=2) 0 => string '' (length=0) 1 => int -1 'query' => array (size=2) 0 => string '?hoge' (length=5) 1 => int 8 3 => array (size=2) 0 => string '?hoge' (length=5) 1 => int 8
しかし、最後のサブパターン(上記の例ではquery
となっている部分)をキャプチャしないようにすると上書きされずにきちんと取得できます。
これを、最後のサブパターンをキャプチャしつつ、host
の値にマッチしたものがセットされるようにしたい場合、処理を2回に分ける以外の方法でどのようにすればよいでしょうか。
できれば一回の処理でそれができるとありがたいので、正規表現のみでの実装が望ましいです。
###追記
ごめんなさい、上記の例だと maisumakun さんの方法で実現はできますが、実現したい処理にはマッチしませんでした。
実装を載せても良いのですが、非常に長く読みづらい為、改めて例を以下に追記致しました。
lang
1$regex = '(?J)(?://(?P<host>a[^?]*)|(?P<host>b[^?]*))?(?P<query>?.*)?'; 2$uri = '//aaabbb?hoge'; 3//$uri = 'bbb?hoge'; // こちらもマッチする 4 5preg_match('`' . $regex . '`i', $uri, $matches, PREG_OFFSET_CAPTURE); 6var_dump($matches);
申し訳ありませんが、追記の例で同じような事をしたい場合をご回答頂けますと幸いです。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2014/10/17 02:00