C#实现DOS通配符“*”和“?”的识别
秒大刀 2007-03-23
DOS通配符在很大程度上可以提高用户使用计算机的效率。本文讲述了怎样使用C#语言实现DOS通配符“*”和“?”的识别。使用的主要技术为正则表达式。
首先要知道Windows或者DOS下命名文件的时候不能包含以下字符:\,/,:,*,?,”,<,>,|。
1. 由于我们这里要使用通配符*和?,所以应该先对用户输入的可能包含通配符的路径名(以下简称“输入”)进行过滤。
2. 再考虑“/”为路径分隔符,所以应该保留。
3. 如果直接根据输入建立正则表达式可能会使得输入中的字符和正则表达式中的关键字符冲突,所以必须先进行置换操作。
4. 经过置换处理后的输入是安全的,这时再将“*”→.*,“?”→.?再在输入末尾加上一个“$”尾字符匹配符以防止对路径的中间合法段匹配。至此,根据输入的正则表达式已经完全建立。
5. 接下来的工作就很简单了,只要使用正则表达式对输入所对应的文件目录下的所有文件名进行逐一的正则匹配即可。
下面的代码段实现了从用户输入得到通配后的文件名集合并存入Queue<string> files的功能:
filename = filename.Trim();//输入-----可能含通配符的文件名
Queue<string> files = new Queue<string>();//输出-----符合输入要求的所在目录的文件名集合
if (filename != null && filename.Length > 0)//确保filename非空
{
if (filename.IndexOfAny(//确保filename中没有非法字符(字符‘/’不能被过滤,因为这个是DOS-Win下的路径分隔符)
new char[] { '<', '>', '/', '\"', '|', ':'}) != -1)
{
Console.WriteLine("文件名{0}非法!", filename);
return;
}
//查看是否有通配符
if (filename.IndexOfAny(new char[] { '?', '*' }) != -1)
{
string currentpath = "";
retry:
if (filename.StartsWith(".\\"))// “.\”处理(当前目录)
{
int lastslash = filename.LastIndexOf('\\');
int length = lastslash - 2;
string sub = filename.Substring(2, length > 0 ? length : 0);
StringBuilder sb = new StringBuilder(Environment.CurrentDirectory);
sb.Append("\\");
sb.Append(sub);
currentpath = sb.ToString();//更新当前目录
filename = filename.Substring(lastslash);
}
else if (filename.StartsWith("..\\"))//“..\”处理(上一级目录)
{
currentpath = Environment.CurrentDirectory;
int lastslash = currentpath.LastIndexOf('\\');
currentpath = currentpath.Substring(0, lastslash);
filename = filename.Substring(3);
goto retry;//处理"..\..\sub\*.*"形式
}
else
{
//得到当前路径下的所有文件名
currentpath = Environment.CurrentDirectory;
}
try
{
//得到当前路径下的所有文件名
currentpath = Environment.CurrentDirectory;
string[] allfilesname = Directory.GetFiles(currentpath);
// \, ^, $, +, {, }, ., [, ], (, )
// 保证正则表达式没有歧义
StringBuilder sb = new StringBuilder(filename);
sb.Replace("\\", "\\\\");
sb.Replace("^", "\\^");
sb.Replace("$", "\\$");
sb.Replace("+", "\\+");
sb.Replace("{", "\\{");
sb.Replace("}", "\\}");
sb.Replace(".", "\\.");
sb.Replace("[", "\\[");
sb.Replace("]", "\\]");
sb.Replace("(", "\\(");
sb.Replace(")", "\\)");
//实现正则表达式对DOS通配符的转换
sb.Replace("*", ".*");
sb.Replace("?", ".?");
sb.Append("$");
Regex regex = new Regex(sb.ToString(), RegexOptions.IgnoreCase);
//用正则表达式对文件名进行过滤
foreach (string str in allfilesname)
{
if (regex.IsMatch(str))
files.Enqueue(str);//保存匹配的文件路径
}
}
catch (Exception ex)
{
ExceptionProcess(ex);//错误处理
}
}
else//没有使用通配符则直接将路径保存
{
files.Enqueue(filename);
}
}
本文关键是利用了正则表达式简化了对通配符的识别。正则表达式在解决一些简单的匹配问题时很有特色,应该引起注意。
有关正则表达式的更多信息:
正则表达式中的标记符号http://dearymz.blog.163.com/blog/static/20565742006313132170
常用的正则表达式http://dearymz.blog.163.com/blog/static/205657420061231119410
评论