字符串与含有通配符‘*’的字符串匹配(非正则表达式)

顺利找到工作之后,每天勤勤恳恳的上班中...

项目需要搜索含有通配符的文件名的文件,*号表示任意多字符。这里应该只处理英文。

 

例,在一个目录里搜索,所有匹配 p_*.pdf 

 

如此简单的要求,还是不要用正则表达式,感觉杀鸡用了牛刀了。

只含有*号的情况就简单的很了,*号匹配任意多字符,首先还是着眼于非*号的文字。

比如 :

 

abcdefg 匹配 a*d*g,这是个通用的匹配,它过了,也就都过了。

 

让我们巧妙的换一个形式来展示这个表达式

a+*d+*g, 这显然可以理解为

1.以a开头的字符串

2.接着是以d结尾的字符串,也就是*d ,在abcdefg中就是bcd

3.接下来是以g结尾的字符串,也就是 *g,即 efg。

 

这么看来,问题就简单明了了。

 

很显然,a应该在开头,g应该在结尾。两个函数StartWith和EndWith,就绝对的保证了开头和结尾。

 

中间,随便匹配一下,也就ok了,鉴于 a*c*e*g形式的存在,匹配还是应该按顺序来。而不是掐头去尾再搜索一下。

 

第一步,把a*c*e*g split数组 [a,c,e,g]

第二步,匹配第一个a,找到之后,将原字符串截掉a 的到bcdefg.

第三步, 匹配c 这里用IndexOf ,找到c的位置,把 c前面的都干掉 得到 defg

这一步的意思实际上是搜索以c为结尾的字符串,也就是 *c。

第四步,找到e的位置,同样干掉前面一节,得到fg。

这时候只剩下g一个匹配项目了,直接endwith即可。

中间任何一步匹配失败,则整体失败。

发个代码,小心了(代码害人):

private bool IsMatch(string src,string pattern)
        {
            string[] ps = pattern.Split('*');
            
            for(int i = 0; i < ps.Length; i++)
            {                
                if(i == 0)
                {
                    if (src.StartsWith(ps[i]))
                    {
                        src = src.Substring(ps[i].Length);
                    }
                    else
                    {
                        return false;
                    }
                }else if (i == ps.Length-1)
                {
                    if (src.EndsWith(ps[i]))
                    {
                        return true;
                    }
                }
                else
                {
                    int p = src.IndexOf(ps[i]);
                    if (p == -1)
                    {
                        return false;
                    }
                    else
                    {
                        src = src.Substring(p + ps[i].Length);
                    }
                }

            }

            return false;
        }

 

posted @ 2019-08-31 16:49  alan0405  阅读(1416)  评论(0编辑  收藏  举报