字符串与含有通配符‘*’的字符串匹配(非正则表达式)
顺利找到工作之后,每天勤勤恳恳的上班中...
项目需要搜索含有通配符的文件名的文件,*号表示任意多字符。这里应该只处理英文。
例,在一个目录里搜索,所有匹配 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; }