[0003]正規表現のマッチでpreg_match_allより自前で作成した方が正確
■正規表現のマッチ処理
まずやりたかったことは、<!--[ で始まり ]--> で終わるものと、<!-- で始まり --> で終わるものの中身を正確に抜き出し、 その文字内の文字を削除することです。また、入れ子になったり、複数存在することもあるので、<!--[ で始まり ]--> で終わるものを優先し、それを全て削除してから次に<!-- で始まり --> で終わるものを処理する必要がありました。
PHPの関数、preg_matchやpreg_match_allを利用しましたが、問題点が2点でてきました。
1つめはメール本文のような長すぎる文字列の場合、ヒットするはずなのにヒットしないということが起こりました。
2つめは複数あり入れ子になっている場合に、終わりを飛ばし、先の終わりまででまとめてしまい、本来間にないはずの部分まで削除してしまいました。
preg_match_allを利用したサンプルは以下です
xxx.php
$pattern = '/<!--\[.*\]-->/s';//<!--[ で始まり ]--> で終わるもの
preg_match_all($pattern, $body,$matchs);
if(_helper_cnt_chk(@$matchs[0]) > 0){
for($mc=0;$mc < _helper_cnt_chk(@$matchs[0]);$mc++){
$body = str_replace(@$matchs[0][$mc], "", $body);
}
}
$pattern = '/<!--.*-->/s';//<!-- で始まり --> で終わるもの
preg_match_all($pattern, $body,$matchs);
if(_helper_cnt_chk(@$matchs[0]) > 0){
for($mc=0;$mc < _helper_cnt_chk(@$matchs[0]);$mc++){
$body = str_replace(@$matchs[0][$mc], "", $body);
}
}
echo $body;
それを自前で作成することにより、やりたかったことが正確に実現できました。
xxx.php
$end_f = 0;
while($end_f ==0){
$start = 0;
$end = 0;
if(strpos($body, '<!--[')) {
$start = strpos($body, '<!--[');
}
if(strpos($body, ']-->')) {
$end = strpos($body, ']-->');
}
if($start != 0 and $end != 0){
$tai = substr($body,$start,$end-$start);
if(!empty($tai)){
$tai = $tai."]-->";
$body = str_replace($tai, "", $body);
}else{
$end_f = 1;//消えないことはないが無限ループ回避
}
}else{
$end_f = 1;
}
}
$end_f = 0;
while($end_f ==0){
$start = 0;
$end = 0;
if(strpos($body, '<!--')) {
$start = strpos($body, '<!--');
}
if(strpos($body, '-->')) {
$end = strpos($body, '-->');
}
if($start != 0 and $end != 0){
$tai = substr($body,$start,$end-$start);
if(!empty($tai)){
$tai = $tai."-->";
$body = str_replace($tai, "", $body);
}else{
$end_f = 1;//消えないことはないが無限ループ回避
}
}else{
$end_f = 1;
}
}
echo $body;