我该如何检查,如果一个文件名通配符模式匹配通配符、我该、文件名、模式

2023-09-02 10:30:41 作者:凉心

我有一个通配符模式,可能的* .txt或POS ?? DAT。

I've got a wildcard pattern, perhaps "*.txt" or "POS??.dat".

我也有在内存中的文件名,我需要比较的模式的列表。

I also have list of filenames in memory that I need to compare to that pattern.

如何做到这一点,记住我需要完全相同的语义IO.DirectoryInfo.GetFiles(模式)使用。

How would I do that, keeping in mind I need exactly the same semantics that IO.DirectoryInfo.GetFiles(pattern) uses.

编辑:盲目地把这种成一个正则表达式将不起作用

Blindly translating this into a regex will NOT work.

推荐答案

我在code为你一个完整的答案是95%,如 FindFiles(字符串)

I have a complete answer in code for you that's 95% like FindFiles(string).

5%,未出现在的 MSDN 文档此功能。

The 5% that isn't there is the short names/long names behavior in the second note on the MSDN documentation for this function.

如果您仍想获得这种行为,你必须完成每一个你输入数组中字符串的短名称的计算,然后就是漫长的名称添加到比赛如果有一个长期的收藏或短名称匹配的模式。

If you would still like to get that behavior, you'll have to complete a computation of the short name of each string you have in the input array, and then add the long name to the collection of matches if either the long or short name matches the pattern.

下面是code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace FindFilesRegEx
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] names = { "hello.t", "HelLo.tx", "HeLLo.txt", "HeLLo.txtsjfhs", "HeLLo.tx.sdj", "hAlLo20984.txt" };
            string[] matches;
            matches = FindFilesEmulator("hello.tx", names);
            matches = FindFilesEmulator("H*o*.???", names);
            matches = FindFilesEmulator("hello.txt", names);
            matches = FindFilesEmulator("lskfjd30", names);
        }

        public string[] FindFilesEmulator(string pattern, string[] names)
        {
            List<string> matches = new List<string>();
            Regex regex = FindFilesPatternToRegex.Convert(pattern);
            foreach (string s in names)
            {
                if (regex.IsMatch(s))
                {
                    matches.Add(s);
                }
            }
            return matches.ToArray();
        }

        internal static class FindFilesPatternToRegex
        {
            private static Regex HasQuestionMarkRegEx   = new Regex(@"?", RegexOptions.Compiled);
            private static Regex IllegalCharactersRegex  = new Regex("[" + @"/:<>|" + ""]", RegexOptions.Compiled);
            private static Regex CatchExtentionRegex    = new Regex(@"^s*.+.([^.]+)s*$", RegexOptions.Compiled);
            private static string NonDotCharacters      = @"[^.]*";
            public static Regex Convert(string pattern)
            {
                if (pattern == null)
                {
                    throw new ArgumentNullException();
                }
                pattern = pattern.Trim();
                if (pattern.Length == 0)
                {
                    throw new ArgumentException("Pattern is empty.");
                }
                if(IllegalCharactersRegex.IsMatch(pattern))
                {
                    throw new ArgumentException("Pattern contains illegal characters.");
                }
                bool hasExtension = CatchExtentionRegex.IsMatch(pattern);
                bool matchExact = false;
                if (HasQuestionMarkRegEx.IsMatch(pattern))
                {
                    matchExact = true;
                }
                else if(hasExtension)
                {
                    matchExact = CatchExtentionRegex.Match(pattern).Groups[1].Length != 3;
                }
                string regexString = Regex.Escape(pattern);
                regexString = "^" + Regex.Replace(regexString, @"\*", ".*");
                regexString = Regex.Replace(regexString, @"\?", ".");
                if(!matchExact && hasExtension)
                {
                    regexString += NonDotCharacters;
                }
                regexString += "$";
                Regex regex = new Regex(regexString, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                return regex;
            }
        }
    }
}