2014-04-08 157 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