首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模式匹配Paths+Files (UNC?)

模式匹配Paths+Files (UNC?)
EN

Stack Overflow用户
提问于 2014-04-08 21:22:54
回答 3查看 3.3K关注 0票数 1

我正在使用C#和2010。我只是尝试匹配一个字符串(在本例中是一个路径),并创建一个模式来帮助我确定它是否是有效的模式。下面的例子是由任意的例子组成的,但是它们确实包含

因此,我正在尝试创建一个模式,它将与UNC路径匹配,该路径是作为字符串传入的。例如:

代码语言:javascript
复制
"\\\\Apple-butter27\\AliceFakePlace\\SomeDay\\Grand100\\Some File Name Stuff\\Yes these are fake words\\One more for fun2000343\\myText.txt"

上面是我正在尝试模式匹配的文件路径的一个例子。我试图将它与以下模式相匹配:

代码语言:javascript
复制
@"\\\\[a-zA-Z0-9-]+\\\w+\\\w+\\\w+\\((\w+)*(\s+)*)*\\((\w+)*(\s+)*)*\\((\w+)*(\s+)*)*\\w+\.txt";

我要注意的是,在我到达我的文件之前,会有7个文件夹。我将不得不寻找一个组合的空格,字母和数字,几乎所有的片段。

我试着从匹配小块开始,比如我的第一次迭代测试--我尝试过这样做,作为我的模式:

代码语言:javascript
复制
@"\\\\";

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

代码语言:javascript
复制
@"\\\\[a-zA-Z0-9-]+";

但失败了。所以我想可能是因为字符串使它加倍,所以我可能不得不加倍我的"\“,所以我再次尝试了8 "\”,但是失败了。

我使用以前的模式的目标是匹配"\\Apple-butter27"

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

如果有人能告诉我这个模式出了什么问题,我会非常感激的。至少有一个起点,因为我知道这是一个很长的时间,如果有人能指出它的一般问题,那么它可能会是一个非常复杂的one...but。

不过,由于它是处于非字符串状态的路径,所以如下所示:

代码语言:javascript
复制
\\Apple-butter27\AliceFakePlace\SomeDay\Grand100\Some File Name Stuff\Yes these are fake words\One more for fun2000343\myText.txt

我刚开始尝试与UNC路径进行模式匹配,所以它开始让我感到困惑,所以如果有人能照亮道路,我会非常感激的。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-08 22:19:46

不需要正则表达式

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

代码语言:javascript
复制
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");
    }
}

指纹:

局部路径 连接到主机‘服务器’

如果你试图与扩展相匹配,不要重新发明轮子,使用Path.GetExtension

代码语言:javascript
复制
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);
}

通常,我建议您在解决问题时避免跳槽。先问问自己是否有人为你解决了这个问题(HTML示例)。对于regex为什么在CodingHorror和(不那么严重的) 论xkcd上的代表不好,有很好的讨论。

Regex版本

如果您决心使用Regex,我认为它不是最佳的工作工具,这是可以做到的。使用间距和注释来确保代码的可读性。

代码语言:javascript
复制
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);
    }
}

打印

代码语言:javascript
复制
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

我猜现在..。

听起来你有某种应用程序,它调用一个目录--它是主目录--并在下面构建一个多层结构。如下所示:

代码语言:javascript
复制
C:\
  root directory for the application\
    site name\
      date of work\
        project name\
          bar\
            actual.txt
            files.txt

你在找真正的文件,或者没有,我看不出来。无论哪种方式,我们都知道C:\root directory\,并认为它可能有实际的文件。然后,我们可以获取目录树并枚举以查找实际文件:

代码语言:javascript
复制
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路径。

票数 6
EN

Stack Overflow用户

发布于 2014-04-08 22:09:59

如果您试图检查路径是否存在,您可以这样做:

代码语言:javascript
复制
FileInfo fi = new FileInfo(@""\\\\Apple-butter27\\AliceFakePlace\\SomeDay\\Grand100\\Some File Name Stuff\\Yes these are fake words\\One more for fun2000343\\myText.txt"");
bool exists = fi.Exists;

但是,如果在运行验证时无法访问这些路径,则可以使用此模式查找\Apple-蝶27:

代码语言:javascript
复制
const string rootPattern = @"(\\\\[a-zA-Z-_0-9]+)";

const RegexOptions regexOptions = RegexOptions.Compiled;

var regex = new Regex(rootPattern, regexOptions);

            foreach (Match match in regex.Matches(fileName))
            {
                if (match.Success && match.Groups.Count >= 1 )
                {
                    shareRoot = match.Groups[0].Value;
                }
            }

我尝试了这种模式,而组0给了我确切的\Apple-蝴蝶27,您将不得不在括号中添加其他字符,比如“.”。

票数 1
EN

Stack Overflow用户

发布于 2014-04-08 23:08:28

虽然我不能不同意System.Uri的用法(这可能是您需要的工具);但我将假设我们严格地需要遵循模式匹配Regex:

代码语言:javascript
复制
        const string tString = "\\\\Apple-butter27\\AliceFakePlace\\SomeDay\\Grand100\\Some File Name Stuff\\Yes these are fake words\\One more for fun2000343\\myText.txt";
        const string tRegexPattern = @"(\\\\)?((?<Folder>[a-zA-Z0-9- ]+)(\\))";
        const RegexOptions tRegexOptions = RegexOptions.Compiled;

        Regex tRegex = new Regex(tRegexPattern, tRegexOptions);

        Console.WriteLine(tString);

        if (tRegex.Matches(tString).Count == 7)
        {
            foreach (Match iMatch in tRegex.Matches(tString))
            {
                if (iMatch.Success && iMatch.Groups["Folder"].Length > 0)
                {
                    Console.WriteLine(iMatch.Groups["Folder"].Value);
                }
            }
        }
        else
            throw new Exception("String did not have a path of depth 7");

虽然可以强制regex只匹配7个组,但Regex实际上是为模式匹配而设计的,而不是“循环逻辑”。

那个?只有在后面跟着分隔符(尾随“\”)时,组才会匹配,因此它只匹配文件夹模式,而不匹配文件或文件扩展名。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22948446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档