65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (53投票s)

2005年9月6日

1分钟阅读

viewsIcon

334291

是否曾想过如何在C#中使用通配符?

引言

你是否想过如何在 .NET 中使用通配符? 这并不难,你只需要使用正则表达式。 但有时弄清楚它也不容易。 我发现我需要花一些时间才能正确地做到这一点。

虽然正则表达式功能更强大,但在用户不了解或不愿学习正则表达式晦涩语法的场景下,通配符仍然很有用。 最明显的例子是几乎所有操作系统的文件搜索功能——很少有不接受通配符的操作系统。 我个人需要通配符来处理 web.config 文件中的 HttpHandlers 标签。

注意:这种方法对于大多数用途来说已经足够好,但如果你需要通配符的每一丝性能,这里是一个好的起点。

Using the Code

将通配符转换为正则表达式有三个步骤

  1. 转义模式,使其对正则表达式安全。 通配符仅使用 *?,因此其余文本必须转换为字面量。
  2. 转义后,* 变为 \*? 变为 \?,因此我们需要将 \*\? 转换为它们各自的正则表达式等效项,即 .*.
  3. 在模式的开头添加 ^,在结尾添加 $,以指定模式的开始和结束。

所以,这就是神奇的函数

public static string WildcardToRegex(string pattern)
{
  return "^" + Regex.Escape(pattern).
  Replace("\\*", ".*").
  Replace("\\?", ".") + "$";
}

为了让它看起来更酷,我将其包装在一个继承 RegexWildcard 类中。

/// <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);
© . All rights reserved.