c# - 模式匹配路径+文件(UNC?)

标签 c# regex pattern-matching unc

我正在使用 C# 和 Visual Studio 2010。我只是想匹配一个字符串(在本例中是一个路径)并创建一个模式来帮助我确定它是否是一个有效模式。以下例子是随意编造的,但确实包含

所以我正在尝试创建一个模式来匹配以字符串形式传入的 UNC 路径。例如:

"\\\\Apple-butter27\\AliceFakePlace\\SomeDay\\Grand100\\Some File Name Stuff\\Yes these are fake words\\One more for fun2000343\\myText.txt"

以上是我尝试进行模式匹配的文件路径示例。我试图将它与这种模式相匹配:

@"\\\\[a-zA-Z0-9-]+\\\w+\\\w+\\\w+\\((\w+)*(\s+)*)*\\((\w+)*(\s+)*)*\\((\w+)*(\s+)*)*\\w+\.txt";

我保证在我找到我的文件之前会有 7 个文件夹。我将不得不为几乎所有的段寻找空格、字母和数字的组合。

我确实尝试从匹配小部分开始,例如我的第一次测试迭代我尝试将其作为我的模式:

@"\\\\";

这是可行的,因为它会匹配前几个字符,但如果我将其添加到它:

@"\\\\[a-zA-Z0-9-]+";

它失败了。所以我想也许是因为字符串导致它加倍,所以我可能不得不加倍我的“\”所以我再次尝试单独使用 8 个“\”,但失败了。

我对之前模式的目标是匹配 "\\\\Apple-butter27"

我一直在 google 和整个网站上查找,但我发现的模式匹配 UNC 内容都不是我的问题。

如果有人能告诉我我在使用此模式时做错了什么,我将不胜感激。至少是一个起点,因为我知道它很长,而且可能会非常复杂……但是如果有人能指出它的一般性问题。

虽然因为它是非字符串状态的路径,它看起来像这样:

\\Apple-butter27\AliceFakePlace\SomeDay\Grand100\Some File Name Stuff\Yes these are fake words\One more for fun2000343\myText.txt

我刚开始尝试使用 UNC 路径进行模式匹配,所以它开始真正让我感到困惑,所以如果有人能指明方向,我将不胜感激。

我正在使用 Regex 的 .Success 函数来查看模式是否匹配,如果匹配成功或失败,我只是打印一条消息。我的主要关注点是模式,除非有一些很好的见解将路径作为解决方案的字符串以外的其他东西使用。

最佳答案

不需要正则表达式

或者,使用 System.Uri 的内置解析类:

foreach (var path in new [] { @"C:\foo\bar\", @"\\server\bar" })
{
    var uri = new Uri(path);

    if (uri.IsUnc)
    {
        Console.WriteLine("Connects to host '{0}'", uri.Host);
    }
    else
    {
        Console.WriteLine("Local path");
    }
}

打印:

Local Path
Connects to host 'server'

如果你想匹配扩展,不要重新发明轮子,使用Path.GetExtension :

var path = "\\some\really long and complicated path\foo.txt";
var extensionOfPath = Path.GetExtension(path);

if (string.Equals(".txt", extensionOfPath, StringComparison.CurrentCultureIgnoreCase))
{
    Console.WriteLine("It's a txt");
}
else
{
    Console.WriteLine("It's a '{0}', which is not a txt", extensionOfPath);
}

一般来说,我试图建议您在解决问题时避免跳转到正则表达式。首先问问自己是否有人为您解决了问题 (example for HTML)。有很好的讨论为什么正则表达式在 CodingHorror 上有不好的代表。和(不太认真)on xkcd .

正则表达式版本

如果您一心想使用正则表达式,我认为这不是完成这项工作的最佳工具,那么您也可以这样做。使用空格和注释来确保您的代码可读。

string input = @"\\Apple-butter27\AliceFakePlace\SomeDay\Grand100\Some File Name Stuff\Yes these are fake words\One more for fun2000343\myText.txt";
Regex regex = new Regex(@"
    ^
    (?:
        # if server is present, capture to a named group
        # use a noncapturing group to remove the surrounding slashes
        # * is a greedy match, so it will butt up against the following directory search
        # this group may or may not occur, so we allow either this or the drive to match (|)
        (?:\\\\(?<server>[^\\]*)\\)
        # if there is no server, then we best have a drive letter
        |(?:(?<drive>[A-Z]):\\)
    )
    # then we have a repeating group (+) to capture all the directory components
    (?:
        # each directory is composed of a name (which does not contain \\)
        # followed by \\
        (?<directory>[^\\]*)\\
    )+
    # then we have a file name, which is identifiable as we already ate the rest of
    # the string.  So, it is just all non-\\ characters at the end.
    (?<file>[^\\]*)
    $", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

var matches = regex.Match(input).Groups;

foreach (var group in regex.GetGroupNames())
{
    Console.WriteLine("Matched {0}:", group);
    foreach (var value in matches[group].Captures.Cast<Capture>())
    {
        Console.WriteLine("\t{0}", value.Value);
    }
}

打印

Matched server:
        Apple-butter27
Matched drive:
Matched directory:
        AliceFakePlace
        SomeDay
        Grand100
        Some File Name Stuff
        Yes these are fake words
        One more for fun2000343
Matched file:
        myText.txt

我现在只是在猜测...

听起来您有某种应用程序调用它的主目录并在其下构建多层结构。类似于以下内容:

C:\
  root directory for the application\
    site name\
      date of work\
        project name\
          bar\
            actual.txt
            files.txt

而您是否正在寻找实际文件,我无法判断。无论哪种方式,我们都知道 C:\root directory\ 并认为它可能有实际文件。然后我们可以获取目录树并枚举以找到实际文件:

var diRoot = new DirectoryInfo(@"C:\drop");

var projectDirectories = FindProjects(diRoot);

// get all of the files in all of the project directories of type .txt
var projectFiles = projectDirectories.SelectMany(di => di.GetFiles("*.txt"));

// projectFiles now contains:
//  actual.txt
//  files.txt

private static IEnumerable<DirectoryInfo> FindProjects(DirectoryInfo cDir, int depth = 0)
{
    foreach (var di in cDir.GetDirectories())
    {
        // assume projects are three levels deep
        if (depth == 3)
        {
            // it's a project, so we can return it
            yield return di;
        }
        else
        {
            // pass it through, return the results
            foreach (var d in FindProjects(di, depth + 1))
                yield return d;
        }
    }
}

而且由于我们不对路径进行字符串操作,因此我们可以透明地处理本地和 UNC 路径。

关于c# - 模式匹配路径+文件(UNC?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22948446/

相关文章:

具有函数指针替换的 C++ 正则表达式库

java - 从行中删除双引号

java - 使用正则表达式提取子字符串

python - 为什么Python 3.10中关键字 `match`可以作为变量名或函数名?

c# - TextBox 不按代码 C# 顺序显示初始文本

c# - 优化 Entity Framework 查询

c# - 在 Visual Studio Code for Mac 上找不到任何 CSX 文件

c# - 如何从 C# 中的资源字典 (XAML) 获取值

java - 解析特定的文本文件java

pattern-matching - 匹配表达式落空?