电子邮件地址拆分

时间:2015-11-11 13:32:30

标签: c#

所以我有一个字符串,我需要用分号

分割

电子邮件地址:"one@tw;,.'o"@hotmail.com;"some;thing"@example.com

这两个电子邮件地址均有效

所以我希望得到以下List<string>

  • “一个@ TW;,”O“。@ hotmail.com
  • “一些;东西” @ example.com

但我目前分割地址的方式不起作用:

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

由于多个;个字符,我最终会收到无效的电子邮件地址。

我尝试过几种不同的方法,如果字符串包含引号,然后找到;字符的索引并按照这种方式进行处理,那么就会解决问题,但这真的很痛苦。

有没有人有更好的建议?

3 个答案:

答案 0 :(得分:13)

假设不允许使用双引号,除了&#34; at&#34;之前的开头报价和收盘价。签署@,您可以使用此正则表达式来捕获电子邮件地址:

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

我们的想法是在[^@"]+之前捕获不带引号的"[^"]*"或引用的@部分,然后将所有内容捕获到分号;或结束锚{ {1}}。

Demo of the regex.

$

此代码打印

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

Demo 1.

如果您希望在双引号内允许转义双引号,则可以使用更复杂的表达式:

"one@tw;,.'o"@hotmail.com
"some;thing"@example.com
hello@world

其他一切都保持不变。

Demo 2.

答案 1 :(得分: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 = "blah@blah.com;\"one@tw;,.'o\"@hotmail.com;\"some;thing\"@example.com;hello@world;asdasd@asd.co.uk;";
            foreach (var email in SplitEmailsByDelimiter(input, ';'))
            {
                Console.WriteLine(email);
            }

会提供此输出

blah@blah.com
"one@tw;,.'o"@hotmail.com
"some;thing"@example.com
hello@world
asdasd@asd.co.uk

答案 2 :(得分: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 = "\"one@tw;,.'o\"@hotmail.com;\"some;thing\"@example.com;hello@world;\"D;D@blah;blah.com\"";
foreach (var address in input.SpecialSplit(';', '"')) 
    Console.WriteLine(v);

虽然给出了这个输出

  

&#34;一个@ TW;,&#39; O&#34; @ hotmail.com

     

&#34;一些;东西&#34; @ example.com

     

您好@世界

     

&#34; d; d @等等; blah.com&#34;

这是使用附加单个转义字符的版本。它假定两个连续的转义字符应该成为一个转义字符,并且它会转义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检查传入的字符串,并注意如果传入一个空字符串,两者都将返回一个带有一个空字符串的序列。