2015-11-11 64 views
10

所以,我有我需要用分號的電子郵件地址拆分

電子郵件地址來分割字符串:"[email protected];,.'o"@hotmail.com;"some;thing"@example.com

兩個電子郵件地址是有效的

所以我想有a List<string>以下:

但我目前分裂地址的方式是行不通的:

var addresses = emailAddressString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) 
       .Select(x => x.Trim()).ToList(); 

由於多個;字符我最終的無效的電郵地址。

我試過幾種不同的方法,即使下去工作,如果字符串包含引號,然後找到;字符的索引,並以這種方式工作,但這是一個真正的痛苦。

有沒有人有更好的建議?

+1

我的建議是,以確保您的分隔符不顯示任何其他地方以外,以紀念邊界在電子郵件之間,所以不應該允許帶'''的電子郵件作爲他們名字的一部分(例如「some; [email protected]」)。否則,找到一個不同的分隔符,如管道'|'? – ray

+0

正規救援?也許你可以適應:http://stackoverflow.com/questions/7430186/regex-split-string-with-on-a-delimetersemi-colon-except-those-that-appear-in – Corak

+1

嘗試以下方法:'(^ |;)(。*?)@([\ d \ w] + [ - ] *)+ \。\ w +' – Camo

回答

4

我明顯開始寫作我的反正則表達式方法大約與juharr同時(另一個答案)。我認爲,既然我已經寫好了,我會提交它。

public static IEnumerable<string> SplitEmailsByDelimiter(string input, char delimiter) 
    { 
     var startIndex = 0; 
     var delimiterIndex = 0; 

     while (delimiterIndex >= 0) 
     { 
      delimiterIndex = input.IndexOf(';', startIndex); 
      string substring = input; 
      if (delimiterIndex > 0) 
      { 
       substring = input.Substring(0, delimiterIndex); 
      } 

      if (!substring.Contains("\"") || substring.IndexOf("\"") != substring.LastIndexOf("\"")) 
      { 
       yield return substring; 
       input = input.Substring(delimiterIndex + 1); 
       startIndex = 0; 
      } 
      else 
      { 
       startIndex = delimiterIndex + 1; 
      } 
     } 
    } 

那麼下面

  var input = "[email protected];\"[email protected];,.'o\"@hotmail.com;\"some;thing\"@example.com;[email protected];[email protected];"; 
      foreach (var email in SplitEmailsByDelimiter(input, ';')) 
      { 
       Console.WriteLine(email); 
      } 

願意給這個輸出

[email protected] 
"[email protected];,.'o"@hotmail.com 
"some;thing"@example.com 
[email protected] 
[email protected] 
13

假定雙引號是不允許的,除了開啓和關閉的「at」符號@行情的未來,你可以使用這個正則表達式捕捉到的電子郵件地址:

((?:[^@"]+|"[^"]*")@[^;]+)(?:;|$) 

的的想法是在@之前捕獲未加引號的[^@"]+或引用的"[^"]*"部分,然後捕獲所有內容,直到分號爲;或結束錨點$

Demo of the regex.

var input = "\"[email protected];,.'o\"@hotmail.com;\"some;thing\"@example.com;[email protected]"; 
var mm = Regex.Matches(input, "((?:[^@\"]+|\"[^\"]*\")@[^;]+)(?:;|$)"); 
foreach (Match m in mm) { 
    Console.WriteLine(m.Groups[1].Value); 
} 

此代碼打印

"[email protected];,.'o"@hotmail.com 
"some;thing"@example.com 
[email protected] 

Demo 1.

如果你想允許雙引號內的轉義雙引號,你可以使用一個更復雜的表達式:

((?:(?:[^@\"]|(?<=\\)\")+|\"([^\"]|(?<=\\)\")*\")@[^;]+)(?:;|$) 

其他一切保持不變。

Demo 2.

+0

謝謝你的幫助。一直把我的頭髮拉出來! –

+0

如果允許雙引號會怎麼樣? –

+0

@JamieR這取決於允許額外的雙引號的規則。如果在引用的字符串中允許使用額外的雙引號,但是它們必須被轉義,那麼正則表達式的這部分''[^「] *」'會變得更加棘手,但仍然可行。允許任何地方不受限制的雙引號曖昧 – dasblinkenlight

3

你也可以做到這一點,而無需使用正則表達式。下面的擴展方法將允許你指定一個分隔字符和一個字符來開始和結束轉義序列。請注意,它不驗證所有轉義序列都已關閉。

public static IEnumerable<string> SpecialSplit(
    this string str, char delimiter, char beginEndEscape) 
{ 
    int beginIndex = 0; 
    int length = 0; 
    bool escaped = false; 
    foreach (char c in str) 
    { 
     if (c == beginEndEscape) 
     { 
      escaped = !escaped; 
     } 

     if (!escaped && c == delimiter) 
     { 
      yield return str.Substring(beginIndex, length); 
      beginIndex += length + 1; 
      length = 0; 
      continue; 
     } 

     length++; 
    } 

    yield return str.Substring(beginIndex, length); 
} 

那麼下面

var input = "\"[email protected];,.'o\"@hotmail.com;\"some;thing\"@example.com;[email protected];\"D;[email protected];blah.com\""; 
foreach (var address in input.SpecialSplit(';', '"')) 
    Console.WriteLine(v); 

雖然給這個輸出

"[email protected];,.'o"@hotmail.com

「一些;事」 @ example.com

hello @ world

「d; d @等等; blah.com」

下面是一個額外的單轉義字符工作的版本。它假設兩個連續的轉義字符應該成爲一個單一的轉義字符,並且它同時逃脫了兩個beginEndEscape章程,所以它不會觸發轉義序列的開始或結束,它也會轉義delimiter。轉義字符後面的任何其他內容都將與轉義字符一起被刪除。

public static IEnumerable<string> SpecialSplit(
    this string str, char delimiter, char beginEndEscape, char singleEscape) 
{ 
    StringBuilder builder = new StringBuilder(); 
    bool escapedSequence = false; 
    bool previousEscapeChar = false; 
    foreach (char c in str) 
    { 
     if (c == singleEscape && !previousEscapeChar) 
     { 
      previousEscapeChar = true; 
      continue; 
     } 

     if (c == beginEndEscape && !previousEscapeChar) 
     { 
      escapedSequence = !escapedSequence; 
     } 

     if (!escapedSequence && !previousEscapeChar && c == delimiter) 
     { 
      yield return builder.ToString(); 
      builder.Clear(); 
      continue; 
     } 

     builder.Append(c); 
     previousEscapeChar = false; 
    } 

    yield return builder.ToString(); 
} 

最後你應該添加null檢查傳遞進來,請注意,這兩個將返回一個序列與一個空字符串,如果你在一個空字符串傳遞字符串。

+0

如果在'''裏面有另一個''''例如''very。(),:; <> [] \「。 \「非常\」非常「@ strange.example.com」 –

+0

在這種情況下,您還需要告訴它雙引號有一個轉義字符,並且您還必須考慮可以和不能轉義的內容。Presumeable「\\」會給你一個單一的反斜槓,但是「\ t」怎麼辦?你想要一個標籤還是隻是單身? – juharr

+3

另外我可能會放棄使用'string.Substring',而是使用'StringBuilder'來添加字符,因爲我循環訪問數據。 – juharr

相關問題