Regex验证文件搜索模式

本文关键字:模式 搜索 文件 验证 Regex | 更新日期: 2023-09-27 18:26:50

我的C#.NET程序使用:

DirInfo.EnumerateFiles(Program.sSourceFilePattern, SearchOption.TopDirectoryOnly)

在文件夹中搜索与"sSourceFilePattern"匹配的文件名。这个搜索模式是用户提供的,我想在执行DirInfo之前验证这个模式。

我在"如何检查给定字符串在Windows下是否是合法/有效的文件名"中找到了regex模式?我取消并修改了它以允许通配符*和?:

sPattern = @"^(?!^(PRN|AUX|CLOCK'$|NUL|CON|COM'd|LPT'd|'..*)('..+)?$)[^'x00-'x1f'':'"";|/]+$";

这种模式运行得相当好,但仍然允许使用涉及多个通配符的无意义模式。例如,这将允许无效的搜索字符串,如:

abc*123.txt
abc*???.txt
*abc.txt

我认为,进一步完善这一点将不仅仅涉及正则表达式,因为它需要应用星号可能出现的位置和后面可能出现的内容的逻辑,无论是在句点(分隔符)之前还是之后,等等。

尽管如此,我还是很感激任何关于改进此正则表达式以捕获更多常见错误的建议。提前感谢!

Regex验证文件搜索模式

我认为星号通配符规则对于我可以设计的任何正则表达式来说都太复杂了,并决定只使用逻辑处理它。事实证明,这比我最初预期的要简单:

if (bResult = Regex.IsMatch(sResult, sPattern, RegexOptions.CultureInvariant))
{
    // Reuse bResult and preset to false.  Only passing all tests sets to true:
    bResult = false;
    // True - no reserved words or illegal characters, so test further.
    // Check wild card placement. '?' may appear anywhere, but '*' follows specific rules.
    // Use LINQ to count occurences of asterisk.  Zero to two is acceptable:
    iCount = sResult.Count(f => f == '*');
    if (iCount == 0)
    {
        // No asterisks, so search pattern testing is finished and the pattern is good.
        bResult = true;
    }
    else if (iCount == 1)
    {
        // One asterisk, so test further.  If one asterisk, it must be last character in string:
        if (sResult.Length == sResult.IndexOf("*")+1)
        {
            // One asterisk and it IS the last character.
            bResult = true;
        }
    }
    else if (iCount == 2)
    {
        // Two asterisks, so test further.  The first asterisk can ONLY be followed
        // by period.  The second asterisk must be the last character in the string:
        iIdx = sResult.IndexOf("*");
        if (sResult.Substring(iIdx+1,1) == ".")
        {
            // First asterisk is followed by period, so test further:
            if (sResult.Length == sResult.LastIndexOf("*")+1)
            {
                // Second asterisk is the last character, so good search pattern.
                bResult = true;
            }
        }
    }
}