https://bugs.php.net/bug.php?id=78853
preg_matchは、パターンにマッチした場合は1を、マッチしなければ0を、エラーが発生したらfalseを返します。
ということでこんな正規表現を試してみましょう。
var_dump(preg_match('/^|\d{1,2}$/', "7"));
なんだこれ?
2が返ってきました。
仕様が変わったけどドキュメントが更新されてなくて古いのかと思えば英語版にもしっかり"1か0かfalseを返す"と書いてあって、ドキュメントが古いわけでもなさそうです。
PHP7.3から発生するようになったみたいなので、ちょっくら原因でも探ってみるかとソースを覗いてみたのですが、
7.3.0
7.2.24
諦めました。
ちなみにPHP7.0でコンパイルオプションpcre.jit
というものが追加され、正規表現にJITを使うようになっています。
このJIT用メモリというのが意外と小さく、たとえば以下の正規表現はpcre.jit
の状態によって返り値が変わってきます。
var_dump(preg_match('/^(A{1,2}B)+$/',str_repeat('AB',8192)));
pcre.jit=0
であれば返り値は正しく1となります。
しかし、デフォルトのpcre.jit=1
であれば返り値はfalseとなり、preg_last_errorにはJIT用メモリが足りないよというPREG_JIT_STACKLIMIT_ERRORが返ってきます。
でもpcre.jit=0
にしても、最初の正規表現では2が返ってきました。
preg_last_errorを確認してもエラーは起こっていないので、pcre.jit
は特に関係ないようです。
さてこのバグですが、先日修正されました。
7.4にもマージされたので、2019/11/28リリース予定のPHP7.4.0正式版ではなおっていると思います。
なお、中身はifをひとつ突っ込んだだけで、どうしてこんなので直るのかさっぱりわかりません。