【PHP】preg_match関数がうまく動かない
preg_match関数で正規表現を使ってマッチ部分を抽出していたが、あるとき、何度も使っていた以下のプログラムの処理が止まりました。
preg_match( "/$area_start(.*?)$area_end/is", $html, $match );
echo $match[1];
プログラムに変更を加えていないのになぜ止まるのか?とプログラムソースをじっくり見てみたが原因不明。
エラーチェック
プログラムが止まる→何かエラーが起きているはずだ!ということで、以下のコードでエラー表示してみました(エラー表示の詳細はこちら)。
error_reporting(-1);
すると、以下のエラーが。そう、どうやらpreg_matchで抽出したデータが入っているはずの「$match[1]」に値がない模様。
Notice: Undefined offset: 1
preg_last_error関数でエラーチェック
preg_match関数で使用していた正規表現は、単純なものだし、これまで何度も使っていたため間違いはないはず。なので抽出できないことは考えられないため、詳細にエラーチェックしました。
preg_last_error();
そこで、「直近の PCRE 正規表現処理のエラーコードを返す」という上記のエラーチェックを行ったところ、「2」という出力が。「2」の意味がわからなかったため、こちらを参考にして以下の方法にチェンジ。
if (preg_last_error() == PREG_NO_ERROR) {
print 'There is no error.';
}
else if (preg_last_error() == PREG_INTERNAL_ERROR) {
print 'There is an internal error!';
}
else if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {
print 'Backtrack limit was exhausted!';
}
else if (preg_last_error() == PREG_RECURSION_LIMIT_ERROR) {
print 'Recursion limit was exhausted!';
}
else if (preg_last_error() == PREG_BAD_UTF8_ERROR) {
print 'Bad UTF8 error!';
}
else if (preg_last_error() == PREG_BAD_UTF8_ERROR) {
print 'Bad UTF8 offset error!';
}
すると、
Backtrack limit was exhausted!(Backtrack limitが足りねぇぞ!)
というエラーが。
Backtrack limitとは?
「Backtrack limit」とは、読んで字のごとくバックトラックのリミット値のことですが、調べてみると、これはPHP5.2.0から導入された以下の2つで設定されているようです。
- pcre.backtrack_limit
PCREのバックトラック処理のリミット値 - pcre.recursion_limit
PCREの再帰処理のリミット値
この2つもしくはいずれかがリミット値を超えた場合、preg_match関数は動かなくなる。
そう、そうなんです。preg_match関数が動かなくなった原因はまさにこれです。今回一気に処理したら楽じゃね?ってノリで扱うデータ量を格段に増やしたんです。
pcre.backtrack_limit値を上げる
ということで、pcre.backtrack_limit値(デフォルトでは100000)を2倍の200000にしたところ、正常にpreg_match関数が動くようになりました。
なお、現在のpcre.backtrack_limit値を確認する方法は、以下を実行すると、その他諸々の情報を参照できます。
phpinfo();
方法
pcre.backtrack_limit値を上げる方法ですが、php.iniを編集するだけです。
php.iniの編集方法は「○○(サーバー名) php.ini 編集方法」などで調べて頂くとして、php.iniに
pcre.backtrack_limit = 200000
と記述するだけです。
なお、さくらインターネットでは、サーバーコントロールパネル→アプリケーションの設定のPHP設定の編集→php.iniの編集の欄に上記を記述すればOKです。
あわせて読んでほしい!
コメント
まだコメントはありません。