该贴中有两种方法可以实现fnmatch函数,现贴如下:
function fnmatch($pattern, $string) //$pattern匹配式, $string被匹配的字符串
{
$starstack = array(); //创建记录pattern开始位置的栈,这个作用是像编辑器的后退
$sstrstack = array(); //创建记录$string开始位置的栈
$countstack = 0; //栈大小,用一个同步记录栈大小,减少count()时所耗的时间
$ptnstart = strlen($pattern) – 1; //定位匹配式最后一个字符, 算法是从字符串后面开始匹配
$strstart = strlen($string) – 1; //定位字符串的最好一个字符
for(; 0 0 && ($pc = $pattern{$ptnstart – 1}) === ‘*’)
$ptnstart –; //while这段是去除几个连续的*号, 并尝试和取得下一个字符
if($ptnstart > 0 && ($pc === $sc || $pc === ‘?’))//比较下个字符是否相同或是?号
{ //如果下一个字符匹配成功
$starstack[$countstack] = $ptnstart;//保存这个*号的位置
$sstrstack[$countstack] = $strstart;//保存$string开始位置
$countstack ++; //栈向下移一
$ptnstart -= 2; //匹配式定位,前移两位,分别是当前*号位和已经匹配的一个
continue; //进行下一次循环
}
}
elseif($pc === ‘?’) //如果匹配式当前字符是?号, 进行?号匹配
{
$ptnstart –; //?号匹配是字符串同步前移一个位置
}
elseif($countstack > 0) //如果不是通配符,检查栈中是否有保存上一个*号的位置
{ //有就还原此*号位置, 回到上一个*号处再次进行匹配
$countstack –;
$ptnstart = $starstack[$countstack];//还原*号位置
$strstart = $sstrstack[$countstack];//还原$string开始位置
}
else
{
return false; //以上情况都没有的话, 匹配失败, 返回flase
}
}
else
{
$ptnstart –; //字符串位置和匹配式位置上相同,前移一位,继续下个匹配
}
} //匹配循环结束
if($ptnstart === -1) //刚好匹配式的位置也结束, 则匹配成功, 返回true
{
return true;
}
elseif($ptnstart >= 0) //匹配式并没有结束, 还有一些没有匹配
{
while($ptnstart > 0 && $pattern{$ptnstart} === ‘*’)//检查剩下的是不是都是*号,去除这些*号
$ptnstart –;
if($pattern{$ptnstart} === ‘*’) //最后的只有一个*号结束的话, 就匹配成功, 返回true
return true;
else
return false; //否则, 返回false
}
return false;
}
if (!function_exists(‘fnmatch’)) {
function fnmatch($pattern, $string) {
return @preg_match(‘/^’ . strtr(addcslashes($pattern, ‘.+^$(){}=!|’), array(‘*’ => ‘.*’, ‘?’ => ‘.?’)) . ‘$/i’, $string);
}
}
这两个方法都可以实现,但由于我要匹配的有包含中文的,比如
我爱中国
匹配 我爱??
就无法实现了,因为“中国”这个字符算4个字符,假如 匹配 我爱???? 应该就没问题了,但是这样对于我们来说使用非常的不方便,于是我改了一个第一个函数的实现,使用mb_strlen的方法来统计和分割字符,实现如下:
function fnmatch($pattern, $string) //$pattern匹配式, $string被匹配的字符串
{
$encoding = gb2312; //根据自己的页面的编码,来定义这个编码
$starstack = array(); //创建记录pattern开始位置的栈,这个作用是像编辑器的后退
$sstrstack = array(); //创建记录$string开始位置的栈
$countstack = 0; //栈大小,用一个同步记录栈大小,减少count()时所耗的时间
$ptnstart = mb_strlen($pattern, $encoding) – 1; //定位匹配式最后一个字符, 算法是从字符串后面开始匹配
$strstart = mb_strlen($string, $encoding) – 1; //定位字符串的最好一个字符
for(; 0 0 && ($pc = mb_substr($pattern, $ptnstart-1, 1, $encoding)) === ‘*’)
$ptnstart –; //while这段是去除几个连续的*号, 并尝试和取得下一个字符
if($ptnstart > 0 && ($pc === $sc || $pc === ‘?’))//比较下个字符是否相同或是?号
{ //如果下一个字符匹配成功
$starstack[$countstack] = $ptnstart;//保存这个*号的位置
$sstrstack[$countstack] = $strstart;//保存$string开始位置
$countstack ++; //栈向下移一
$ptnstart -= 2; //匹配式定位,前移两位,分别是当前*号位和已经匹配的一个
continue; //进行下一次循环
}
}
elseif($pc === ‘?’) //如果匹配式当前字符是?号, 进行?号匹配
{
$ptnstart –; //?号匹配是字符串同步前移一个位置
}
elseif($countstack > 0) //如果不是通配符,检查栈中是否有保存上一个*号的位置
{ //有就还原此*号位置, 回到上一个*号处再次进行匹配
$countstack –;
$ptnstart = $starstack[$countstack];//还原*号位置
$strstart = $sstrstack[$countstack];//还原$string开始位置
}
else
{
return false; //以上情况都没有的话, 匹配失败, 返回flase
}
}
else
{
$ptnstart –; //字符串位置和匹配式位置上相同,前移一位,继续下个匹配
}
} //匹配循环结束
if($ptnstart === -1) //刚好匹配式的位置也结束, 则匹配成功, 返回true
{
return true;
}
elseif($ptnstart >= 0) //匹配式并没有结束, 还有一些没有匹配
{
while($ptnstart > 0 && mb_substr($pattern, $ptnstart, 1, $encoding) === ‘*’)//检查剩下的是不是都是*号,去除这些*号
$ptnstart –;
if(mb_substr($pattern, $ptnstart, 1, $encoding) === ‘*’) //最后的只有一个*号结束的话, 就匹配成功, 返回true
return true;
else
return false; //否则, 返回false
}
return false;
}
实现完毕,可完美匹配中文了。
http://www.bkjia.com/phpjc/621633.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/621633.htmltecharticle该贴中有两种方法可以实现fnmatch函数,现贴如下: function fnmatch($pattern, $string) //$pattern匹配式, $string被匹配的字符串{ $starstack = array(); //创…