将通配符转换为正则表达式






4.78/5 (53投票s)
2005年9月6日
1分钟阅读

334291
是否曾想过如何在C#中使用通配符?
引言
你是否想过如何在 .NET 中使用通配符? 这并不难,你只需要使用正则表达式。 但有时弄清楚它也不容易。 我发现我需要花一些时间才能正确地做到这一点。
虽然正则表达式功能更强大,但在用户不了解或不愿学习正则表达式晦涩语法的场景下,通配符仍然很有用。 最明显的例子是几乎所有操作系统的文件搜索功能——很少有不接受通配符的操作系统。 我个人需要通配符来处理 web.config 文件中的 HttpHandlers
标签。
注意:这种方法对于大多数用途来说已经足够好,但如果你需要通配符的每一丝性能,这里是一个好的起点。
Using the Code
将通配符转换为正则表达式有三个步骤
- 转义模式,使其对正则表达式安全。 通配符仅使用
*
和?
,因此其余文本必须转换为字面量。 - 转义后,
*
变为\*
,?
变为\?
,因此我们需要将\*
和\?
转换为它们各自的正则表达式等效项,即.*
和.
。 - 在模式的开头添加
^
,在结尾添加$
,以指定模式的开始和结束。
所以,这就是神奇的函数
public static string WildcardToRegex(string pattern)
{
return "^" + Regex.Escape(pattern).
Replace("\\*", ".*").
Replace("\\?", ".") + "$";
}
为了让它看起来更酷,我将其包装在一个继承 Regex
的 Wildcard
类中。
/// <summary>
/// Represents a wildcard running on the
/// <see cref="System.Text.RegularExpressions"/> engine.
/// </summary>
public class Wildcard : Regex
{
/// <summary>
/// Initializes a wildcard with the given search pattern.
/// </summary>
/// <param name="pattern">The wildcard pattern to match.</param>
public Wildcard(string pattern)
: base(WildcardToRegex(pattern))
{
}
/// <summary>
/// Initializes a wildcard with the given search pattern and options.
/// </summary>
/// <param name="pattern">The wildcard pattern to match.</param>
/// <param name="options">A combination of one or more
/// <see cref="System.Text.RegexOptions"/>.</param>
public Wildcard(string pattern, RegexOptions options)
: base(WildcardToRegex(pattern), options)
{
}
/// <summary>
/// Converts a wildcard to a regex.
/// </summary>
/// <param name="pattern">The wildcard pattern to convert.</param>
/// <returns>A regex equivalent of the given wildcard.</returns>
public static string WildcardToRegex(string pattern)
{
return "^" + Regex.Escape(pattern).
Replace("\\*", ".*").
Replace("\\?", ".") + "$";
}
}
你可以像使用任何其他 Regex
一样使用它——大小写(不)敏感、字符串替换、匹配等等。
// Get a list of files in the My Documents folder
string[] files = System.IO.Directory.GetFiles(
System.Environment.GetFolderPath(
Environment.SpecialFolder.Personal));
// Create a new wildcard to search for all
// .txt files, regardless of case
Wildcard wildcard = new Wildcard("*.txt", RegexOptions.IgnoreCase);
// Print all matching files
foreach(string file in files)
if(wildcard.IsMatch(file))
Console.WriteLine(file);