LoginSignup
1
0

More than 3 years have passed since last update.

[PHP] ereg() から preg_match() への変更でチョットした留意点

Last updated at Posted at 2020-05-22

PHP7ではereg()が廃止となりpreg_match()を利用することになりました。
古いコードの書き換えをされている方もいると思います。

ereg()をpreg_match()に変更し
マッチングパターンをPOSIXからPCREに書き換えると各所で紹介されていますね。

ちょっと見落としがちかなと思うのは戻り値の違いです。
自分は望む結果が得られずに?となりましたので記事に残しておきます。

ereg()もpreg_match()もint型の戻り値を返しますが

ereg()
 マッチした場合にはマッチした文字列の長さを返し、
 マッチしなかった場合 またはエラーとなった場合は FALSE を返します。
preg_match()
 マッチした場合に 1 を返します。 マッチしなかった場合は 0、エラーが発生した場合は FALSE を返します。

という違いがあります。
マッチング結果を使用して何か処理を行う場合、結果に違いが生じるかもしれません。

<?php
$string = 'ab123cdefg@abcd678efg@a456bcdeg';        // 評価文字列
$pattern = '([a-z]+@)';                             // @とその前のアルファベット(不定長)を検出
while($Ret = ereg($pattern, $string, $matches)){    // $Ret マッチした文字列の長さ
    $pos = strpos($string, $matches[0]);            // $pos マッチした文字列が最初に現れた場所
    $string = substr($string, $pos + $Ret);         // $pos + $Ret を切り捨て評価文字列を再作成
    $result[] = $string;
}
var_dump($result);
?>

-- 結果 ------------------------------------------
array (size=2)
  0 => string 'abcd678efg@a456bcdeg' (length=20)
  1 => string 'a456bcdeg' (length=9)

このようなコードのereg()をpreg_match()に置き換えるだけだと

<?php
$string = 'ab123cdefg@abcd678efg@a456bcdeg';
$pattern = '/([a-z]+@)/';                                // PCREパターンに書き換え
while($Ret = preg_match($pattern, $string, $matches)){   // preg_match に変更、$Retに真偽値 1 が入る
    $pos = strpos($string, $matches[0]);
    $string = substr($string, $pos + $Ret);          // $Retが真偽値の為 $pos + 1 しか切り捨てない
    $result[] = $string;
}
var_dump($result);
?>

-- 結果 ------------------------------------------------
array (size=8)
  0 => string 'defg@abcd678efg@a456bcdeg' (length=25)
  1 => string 'efg@abcd678efg@a456bcdeg' (length=24)
  2 => string 'fg@abcd678efg@a456bcdeg' (length=23)
  3 => string 'g@abcd678efg@a456bcdeg' (length=22)
  4 => string '@abcd678efg@a456bcdeg' (length=21)
  5 => string 'fg@a456bcdeg' (length=12)
  6 => string 'g@a456bcdeg' (length=11)
  7 => string '@a456bcdeg' (length=10)

という具合に結果が変わってしまいます。
マッチした文字列長を後で取得することにします。

<?php
$string = 'ab123cdefg@abcd678efg@a456bcdeg';
$pattern = '/([a-z]+@)/';
while(preg_match($pattern, $string, $matches)){   // 戻り値は格納しない
    $pos = strpos($string, $matches[0]);
    $pos += strlen($matches[0]);                  // strlenでマッチした文字列長を取得
    $string = substr($string, $pos);
    $result[] = $string;
}
var_dump($result);
?>

-- 結果 -------------------------------------------
array (size=2)
  0 => string 'abcd678efg@a456bcdeg' (length=20)
  1 => string 'a456bcdeg' (length=9)

これで変更前と同じ結果が得られました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0