热门标签 | HotTags
当前位置:  开发笔记 > 开发工具 > 正文

php适用于windows的fnmatch(匹配函数),可匹配中文。

该贴中有两种方法可以实现fnmatch函数,现贴如下:functionfnmatch($pattern,$string)$pattern匹配式,$string被匹配的字符串{$starStack=array();

 

该贴中有两种方法可以实现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 <= $strStart; $strStart --)     //开始匹配循环, 每匹配一个字符, $strStart就往前移一个字符
    {
        $sc = $string{$strStart};           //取得当前在比较的字符
        $pc = ($ptnStart <0) ? &#39;&#39; : $pattern{$ptnStart};//取得匹配式当前的字符,已到结束位置,给个空
        if($sc !== $pc)
        {                                   //当两个字符不相同时, 就要进行一些匹配式特殊字符的比较
            if($pc === &#39;*&#39;)                 //如果匹配式当前字符是*号, 进行*号匹配
            {
                while($ptnStart > 0 && ($pc = $pattern{$ptnStart - 1}) === &#39;*&#39;)
                    $ptnStart --;           //while这段是去除几个连续的*号, 并尝试和取得下一个字符
                if($ptnStart > 0 && ($pc === $sc || $pc === &#39;?&#39;))//比较下个字符是否相同或是?号
                {                           //如果下一个字符匹配成功
                    $starStack[$countStack] = $ptnStart;//保存这个*号的位置
                    $sstrStack[$countStack] = $strStart;//保存$string开始位置
                    $countStack ++;         //栈向下移一
                    $ptnStart -= 2;         //匹配式定位,前移两位,分别是当前*号位和已经匹配的一个
                    continue;               //进行下一次循环
                }
            }
            elseif($pc === &#39;?&#39;)             //如果匹配式当前字符是?号, 进行?号匹配
            {
                $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} === &#39;*&#39;)//检查剩下的是不是都是*号,去除这些*号
            $ptnStart --;
        if($pattern{$ptnStart} === &#39;*&#39;)     //最后的只有一个*号结束的话, 就匹配成功, 返回true
            return true;
        else
            return false;                   //否则, 返回false
    }
    return false;
}

if (!function_exists(&#39;fnmatch&#39;)) {
        function fnmatch($pattern, $string) {
            return @preg_match(&#39;/^&#39; . strtr(addcslashes($pattern, &#39;.+^$(){}=!<>|&#39;), array(&#39;*&#39; => &#39;.*&#39;, &#39;?&#39; => &#39;.?&#39;)) . &#39;$/i&#39;, $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 <= $strStart; $strStart --)     //开始匹配循环, 每匹配一个字符, $strStart就往前移一个字符
    {
		$sc = mb_substr($string, $strStart, 1, $encoding);           //取得当前在比较的字符
		$pc = ($ptnStart <0) ? &#39;&#39; : mb_substr($pattern, $ptnStart, 1, $encoding);//取得匹配式当前的字符,已到结束位置,给个空
        if($sc !== $pc)
        {                                   //当两个字符不相同时, 就要进行一些匹配式特殊字符的比较
            if($pc === &#39;*&#39;)                 //如果匹配式当前字符是*号, 进行*号匹配
            {
                while($ptnStart > 0 && ($pc = mb_substr($pattern, $ptnStart-1, 1, $encoding)) === &#39;*&#39;)
                    $ptnStart --;           //while这段是去除几个连续的*号, 并尝试和取得下一个字符
                if($ptnStart > 0 && ($pc === $sc || $pc === &#39;?&#39;))//比较下个字符是否相同或是?号
                {                           //如果下一个字符匹配成功
                    $starStack[$countStack] = $ptnStart;//保存这个*号的位置
                    $sstrStack[$countStack] = $strStart;//保存$string开始位置
                    $countStack ++;         //栈向下移一
                    $ptnStart -= 2;         //匹配式定位,前移两位,分别是当前*号位和已经匹配的一个
                    continue;               //进行下一次循环
                }
            }
            elseif($pc === &#39;?&#39;)             //如果匹配式当前字符是?号, 进行?号匹配
            {
                $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) === &#39;*&#39;)//检查剩下的是不是都是*号,去除这些*号
            $ptnStart --;
        if(mb_substr($pattern, $ptnStart, 1, $encoding) === &#39;*&#39;)     //最后的只有一个*号结束的话, 就匹配成功, 返回true
            return true;
        else
            return false;                   //否则, 返回false
    }
    return false;
}

实现完毕,可完美匹配中文了。

 


推荐阅读
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Søren Kierkegaard famously stated that life can only be understood in retrospect but must be lived moving forward. This perspective delves into the intricate relationship between our lived experiences and our reflections on them. ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 计算机网络复习:第五章 网络层控制平面
    本文探讨了网络层的控制平面,包括转发和路由选择的基本原理。转发在数据平面上实现,通过配置路由器中的转发表完成;而路由选择则在控制平面上进行,涉及路由器中路由表的配置与更新。此外,文章还介绍了ICMP协议、两种控制平面的实现方法、路由选择算法及其分类等内容。 ... [详细]
  • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
  • 线性Kalman滤波器在多自由度车辆悬架主动控制中的应用研究
    本文探讨了线性Kalman滤波器(LKF)在不同自由度(2、4、7)的车辆悬架系统中进行主动控制的应用。通过详细的仿真分析,展示了LKF在提升悬架性能方面的潜力,并总结了调参过程中的关键要点。 ... [详细]
  • 本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 本文介绍如何利用动态规划算法解决经典的0-1背包问题。通过具体实例和代码实现,详细解释了在给定容量的背包中选择若干物品以最大化总价值的过程。 ... [详细]
  • 本文详细探讨了Java中的24种设计模式及其应用,并介绍了七大面向对象设计原则。通过创建型、结构型和行为型模式的分类,帮助开发者更好地理解和应用这些模式,提升代码质量和可维护性。 ... [详细]
author-avatar
深耐猪老汉11_245
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有