2015-11-11 5 views
10

だから、私はセミコロンのメールアドレス分割

メールアドレスで分割する必要がある文字列があります。"[email protected];,.'o"@hotmail.com;"some;thing"@example.comは、電子メールアドレスの両方が有効である

だから私は持っていると思いますが次のうちの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

二重引用符は、開口部を除いて、許可されていないと仮定すると、今後の@に署名、電子メールアドレスをキャプチャするために、この正規表現を使用することができます「の」の引用符を閉じる:

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

引用符で囲まれていない[^@"]+または引用符付きの部分を@の前にキャプチャし、セミコロン;または終了アンカー$までのすべてをキャプチャすることです。

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

ありがとうございます。この1つについて私の髪を引っ張っていた! –

+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"

ここでは、追加のシングルエスケープ文字で動作するバージョンがあります。 2つの連続したエスケープ文字が1つのエスケープ文字になるはずで、エスケープシーケンスの開始または終了をトリガーしないように、delimiterをエスケープするようにbeginEndEscapeチャーターの両方をエスケープしていると仮定します。エスケープ文字の後に来るものは、エスケープ文字をそのままにしてそのまま残ります。

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あなたは空の文字列を渡した場合の両方が1つの空の文字列でのシーケンスを返すことで渡された文字列とノートのチェックを追加する必要があります。

+0

'' 'の中に' '非常に。()、:; <> [] \"があるとどうなりますか?非常に@ \\ \ "非常に\"。珍しい "@ strange.example.com' –

+0

この場合、二重引用符のエスケープ文字があることを伝える必要があります。また、エスケープできることとできないことについて考える必要があります"\\"はあなたに単一のバックスラッシュを与えますが、 "\ t"はどうでしょうか?シングル? – juharr

+3

また、 'string.Substring'を使用しないで、代わりに' StringBuilder'を使用してデータをループするときに文字を追加することもできます。 – juharr