2014-04-08 106 views
1

我正在使用C#和Visual Studio 2010.我只是想匹配一个字符串(这是一个路径在这种情况下),并创建一个模式,将帮助我弄清楚如果这是一个有效的模式与否。下面的例子是由任意组成的,但他们确实包含模式匹配路径+文件(UNC?)

所以我想创建一个模式,将匹配一个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个文件夹,直到我达到我的文件(S)。我将不得不为所有细分市场寻找空格,字母和数字组合。

我曾尝试通过小位开始匹配,如我的测试中第一次迭代我想这是我的模式:

@"\\\\"; 

而且这个工程,因为它会匹配前几个字符,但如果我添加这对它:

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

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

我与以前的模式的目标是匹配“\\\\苹果butter27”

我一直在寻找对谷歌和所有在这个网站,但没有一个模式匹配UNC的东西,我发现是我的问题。

我真的很感激,如果有人能告诉我我在做什么这个模式错了。至少有一个起点,因为我知道这很长,可能会是一个非常复杂的问题......但是如果有人能指出一些普通的东西是错误的。

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

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

我新的尝试模式与UNC路径匹配,所以它开始真正迷惑我,所以如果有人能照亮方式,我会很感激。

我正在使用。成功正则表达式的函数来查看模式是否匹配,如果匹配成功或失败,我只是在打印消息。我的主要焦点是模式,除非有一些很好的洞察力,将解决方案的字符串用作路径而不是字符串。

+0

我会建议不要总是假设正则表达式是所有问题的最佳工具!由于您的假设,这是[XY问题](http://meta.stackexchange.com/a/66378)。 –

+0

我在想Regex是我的解决方案。我想验证路径是否是某种特定的方式,如果不是这样,我希望它停止沿某个文件路径前进,并继续向其他人查找它想要的信息。 – user3003304

回答

6

没有正则表达式需要

或者,使用内置在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"); 
    } 
} 

打印:

本地路径
连接到主机 '服务器'

如果你想对阵的延长,不重新发明轮子,用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路径。

+0

我真的不介意一个文件夹是否存在,我已经得到了支票。我正在做一堆文件夹潜水,而且我可以很容易地做到这一点,但我想通过说一些类似于“如果不是这样,然后不要打扰”来切断某些路径来缩短时间看着它“。所以文件夹有一个命名约定,但我最终只是试图切断一些不必要的文件夹潜水。我相信正则表达式就是解决方案,否则我不知道你会怎么做“如果不是这样,就不要这样做”。 – user3003304

+0

恐怕我不明白你在做什么。 “Uri”和“Path”都不需要或检查磁盘上是否存在文件,对于这个问题也不是正则表达式。正则表达式在匹配常规字符串时非常有用(例如:tmp314 - >'tmp \ d {3}'),用户生成的路径是_anything but_ regular。 – Mitch

+0

我的代码是基于http://msdn.microsoft.com/en-us/library/bb513869.aspx我用它来处理文件的东西。我需要检查路径中的一些东西,这就是我使用正则表达式的原因。我没有用它来做任何关于查找文件的事情,我希望用它来说“如果像这样,不要去那里”。这是正则表达式的目标。 – user3003304

1

如果你想检查是否存在路径,你可以做这样的事情:

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; 

但是,如果你没有访问点在哪里运行验证这些路径,你可以用这个模式来查找\\苹果butter27:

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给了我到底\\苹果butter27 你将不得不在括号[]中添加其他字符,你可能遭遇如可能是'。'。

0

虽然我不能不同意使用系统。Uri(这可能是你需要的工具);我认为,我们需要严格坚持一个模式匹配正则表达式:

 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"); 

虽然你可以强制正则表达式来仅匹配7组,正则表达式是真正专为模式匹配,而不是“糊涂的逻辑”。

The? <文件夹>组只会在匹配后跟分隔符(尾随'\'),因此它只会匹配文件夹模式而不匹配文件或文件扩展名。

+0

这个失败了,你有人命名一个带有下划线的文件,或者一个带有句点的目录,或者其他几千个名字中允许的字符。不要介意这种解决方案本地化的不可能性。 – Mitch