【PHP】preg_match関数がうまく動かない

公開日:
更新日:
カテゴリー: PHP

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です。

 

あわせて読んでほしい!

 

コメント

まだコメントはありません。

コメントフォーム
お名前
コメント