旧それなりブログの跡地、画像やスタイルやJSなどが壊れてることがあります。

eregはPOSIX NFAエンジンじゃないっぽい

2007年4月29日

ereg関数ってのは、PHPの正規表現用の関数なんですが
この挙動がおかしいという話です。

「おかしい」ってのは、オライリーの正規表現本に書いてある内容と反しているってことです。
申し訳ありませんが、それ以外の基準を知らないので、用語とかもそれに準拠します。

で、何がおかしいかというと
例えば

<?php
$p = '^(abc|[a-z]+)';
$s = 'abcdefghi'
$m = array();
ereg($p, $s, $m);
var_dump($m[1]); // 1番目のサブパターンにマッチした内容を出力する
?>

これを実行した場合に、
仮に従来型のNFAエンジンなら
最初にマッチングする”abc”が1番目のサブパターンのマッチとして格納されるはず。

また、POSIX準拠NFAエンジンなら、
最もマッチ範囲の大きい”abcdefghi”が1番目のサブパターンのマッチとして格納されるはず。

またまた、DFAエンジンなら、そもそもサブパターンによるマッチが出来ないはず。

ということで実行すると “abcdefghi”を出力するので、
「あー、やっぱりPOSIX NFAか」と思いましたが・・・が
念のため、↓的な、POSIX NFAの場合にフリーズするような奴で実行してみたら

<?php
$p = '.*.*.*.*.*.*.*.*.*.*';
$s = 'aaaaaaaaaa'
$m = array();
ereg($p, $s, $m);
?>

・・・あれ?すぐ返ってくるな。

んで、続けて調べていると

<?php
$p = '123|[a-z]+';
$s = '123abcdef';
$m = array();
ereg($p, $s, $m);
var_dump($m[0]); // "123"を出力
?>

・・・?
POSIX NFA なら、”abcdef”を返すはずなんだけど・・・??

しつこく実行

<?php
$p = 'abc|[a-z]+';
$s = '123abcdef';
$m = array();
ereg($p, $s, $m);
var_dump($m[0]); // "abcdef"を出力
?>

・・・??
アルファベット同士なら、長い方を返してくれるのかな??

どうにもereg関数は、
NFAとかPOSIXとか関係無しに、単なる独自仕様の関数っぽいです。
暇だったら、頑張ってCのソースでも追ってみようかと思います。

俺、C言語読めないジャン