.NET中的glob模式匹配

dmo*_*dmo 46 .net c# glob

.NET中是否有内置机制来匹配正则表达式以外的模式?我想使用UNIX样式(glob)通配符匹配(*=任何数字的任何字符).

我想将它用于面向最终用户的控件.我担心允许所有RegEx功能会非常混乱.

min*_*.dk 63

我喜欢我的代码更加语义,所以我编写了这个扩展方法:

using System.Text.RegularExpressions;

namespace Whatever
{
    public static class StringExtensions
    {
        /// <summary>
        /// Compares the string against a given pattern.
        /// </summary>
        /// <param name="str">The string.</param>
        /// <param name="pattern">The pattern to match, where "*" means any sequence of characters, and "?" means any single character.</param>
        /// <returns><c>true</c> if the string matches the given pattern; otherwise <c>false</c>.</returns>
        public static bool Like(this string str, string pattern)
        {
            return new Regex(
                "^" + Regex.Escape(pattern).Replace(@"\*", ".*").Replace(@"\?", ".") + "$",
                RegexOptions.IgnoreCase | RegexOptions.Singleline
            ).IsMatch(str);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

(更改命名空间和/或将扩展方法复制到您自己的字符串扩展类)

使用此扩展,您可以编写如下语句:

if (File.Name.Like("*.jpg"))
{
   ....
}
Run Code Online (Sandbox Code Playgroud)

只是糖,使你的代码更清晰:-)

  • 我从这篇文章中学到了三件新东西. (8认同)
  • 优秀的方法.我会将参数重命名为`pattern`以避免混淆它自己设置通配符. (2认同)

Jon*_*son 36

我找到了你的实际代码:

Regex.Escape( wildcardExpression ).Replace( @"\*", ".*" ).Replace( @"\?", "." );
Run Code Online (Sandbox Code Playgroud)

  • 你可能还想在之前添加一个"^",并在结尾处使用"$"来模仿UNIX/DOS通配,对吧? (5认同)
  • 我想我会用@"[^ \\\.]*"替换"\*" - 暗示除了点或斜线之外的任何字符,它们在文件名格式中都是有意义的. (2认同)
  • 要正确支持通配符转义和东西,你需要比`string.Replace()`更复杂的东西.这段代码将用户提供的`\*`转换为`\\.*`的正则表达式,它与输入字符串`*`不匹配. (2认同)

cle*_*ris 25

只是为了完整.自2016年以来,dotnet core有一个名为Microsoft.Extensions.FileSystemGlobbing支持高级全球路径的新nuget包.(Nuget套餐)

一些例子可能是,搜索在Web开发场景中非常常见的通配符嵌套文件夹结构和文件.

  • wwwroot/app/**/*.module.js
  • wwwroot/app/**/*.js

这与.gitignore用于确定要从源代码管理中排除哪些文件的文件有些类似.

  • 我将此添加到我的C#控制台应用程序(50行代码)中,NuGet提取了280兆字节的软件包依赖项.所以它可能不适合所有场景(或者如果有人知道如何减少它......) (2认同)
  • 请注意,自2018年12月起,"Microsoft.Extensions.FileSystemGlobbing"仍然不能与"组合"文件(即远程或卸载文件)一起使用.请参阅https://github.com/aspnet/Extensions/issues/848对于这个特殊情况,我使用了DotNet.Glob nuget软件包(/sf/answers/3659732121/),它快速而小巧. (2认同)
  • 我最终搜索了“/*”并使用该索引之前的所有内容(如果存在)作为基本路径,并将之后的所有内容用作全局路径。似乎工作正常。 (2认同)

Dan*_*lli 10

列表方法的2和3参数变体喜欢GetFiles()并将EnumerateDirectories()搜索字符串作为支持文件名通配的第二个参数,使用*?.

class GlobTestMain
{
    static void Main(string[] args)
    {
        string[] exes = Directory.GetFiles(Environment.CurrentDirectory, "*.exe");
        foreach (string file in exes)
        {
            Console.WriteLine(Path.GetFileName(file));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

会屈服

GlobTest.exe
GlobTest.vshost.exe
Run Code Online (Sandbox Code Playgroud)

文档声明存在一些具有匹配扩展的警告.它还指出8.3文件名是匹配的(可能在幕后自动生成),这可能导致给定某些模式的"重复"匹配.

支持此方法是GetFiles(),GetDirectories()GetFileSystemEntries().该Enumerate变种也支持这一点.


Ton*_*mbe 7

如果你想避免正则表达式,这是一个基本的 glob 实现:

public static class Globber
{
    public static bool Glob(this string value, string pattern)
    {
        int pos = 0;

        while (pattern.Length != pos)
        {
            switch (pattern[pos])
            {
                case '?':
                    break;

                case '*':
                    for (int i = value.Length; i >= pos; i--)
                    {
                        if (Glob(value.Substring(i), pattern.Substring(pos + 1)))
                        {
                            return true;
                        }
                    }
                    return false;

                default:
                    if (value.Length == pos || char.ToUpper(pattern[pos]) != char.ToUpper(value[pos]))
                    {
                        return false;
                    }
                    break;
            }

            pos++;
        }

        return value.Length == pos;
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

Assert.IsTrue("text.txt".Glob("*.txt"));
Run Code Online (Sandbox Code Playgroud)


Dar*_*ell 6

我为 .NETStandard 编写了一个通配库,其中包含测试和基准测试。我的目标是为 .NET 生成一个具有最小依赖性的库,该库不使用正则表达式,并且性能优于正则表达式。

你可以在这里找到它:


tor*_*ial 5

如果使用VB.Net,则可以使用Like语句,它具有类似Glob的语法.

http://www.getdotnetcode.com/gdncstore/free/Articles/Intoduction%20to%20the%20VB%20NET%20Like%20Operator.htm

  • 上面的教程链接也特定于 VB.Net。 (2认同)