c#中一个优雅的分隔逗号分隔的电子邮件地址列表的方法

本文关键字:分隔 电子邮件地址 方法 列表 一个 | 更新日期: 2023-09-27 18:18:43

看所以有各种方法来解决这个问题,但是推荐的解决方案,例如不处理'"最后,第一'" "和richard在该帖子中发布的建议是缺少代码SetUpTextFieldParser()

我有以下电子邮件地址列表作为字符串:

string str = "Last, First <name@domain.com>, name@domain.com, First Last <name@domain.com>, '"First Last'" <name@domain.com>, '"Last, First'" <name@domain.com>";

当前代码做a:

str.Split(",");

因为:

中的逗号而产生了一个不正确的列表
"Last, First"

有谁有什么好的东西可以分享吗?这样我就能得到一个字符串数组,格式为:

Last, First <name@domain.com>
name@domain.com
First Last <name@domain.com>
"First Last" <name@domain.com>
"Last, First" <name@domain.com>

EDIT - SOLUTION

我最终使用了Yacoub Massad的解决方案,因为它很简单(正则表达式在我的开发小组中很难维护,因为不是每个人都理解它们)。下面是代码(Fiddle),其中添加了一些内容,并进行了简单的测试,以确保一切正常:

  • 后面逗号以防有人粗心
  • 从MSDN页面添加(注释)电子邮件地址格式

_

using System;
using System.Collections.Generic;
using System.Net.Mail;
public class Program
{
    public static void Main()
    {
        //https://msdn.microsoft.com/en-us/library/system.net.mail.mailaddress(v=vs.110).aspx
        //Some esoteric "comment" formats as well as a trailing comma in case someone did not tidy up
        string emails = "Last, First <name@domain.com>, name@domain.com, First Last <name@domain.com>, '"First Last'" <name@domain.com>, '"Last, First'" <name@domain.com>,  (comment)'"First, Last'"(comment)<(comment)joe(comment)@(comment)there.com(comment)>(comment),";
        List<string> result = new List<string>();
        Console.WriteLine("LOOP");
        while (true)
        {
            int position_of_at = emails.IndexOf("@");
            if (position_of_at == -1)
            {
                break;
            }
            int position_of_comma = emails.IndexOf(",", position_of_at);
            if (position_of_comma == -1)
            {
                result.Add(emails);
                break;
            }
            string email = emails.Substring(0, position_of_comma);
            result.Add(email);
            emails = emails.Substring(position_of_comma + 1);
        }
        Console.WriteLine("/LOOP");
        //Do some very basic validation of above code
        var i = 1;
        if (result.Count == 6)
            Console.WriteLine("SUCCESS: " + result.Count);
        else
            Console.WriteLine("FAILURE: " + result.Count);
        foreach (string emailAddress in result)
        {
            Console.WriteLine("==== " + i.ToString());
            Console.WriteLine(emailAddress);
            Console.WriteLine("/====");
            MailAddress mailAddress = new MailAddress(emailAddress);
            Console.WriteLine(mailAddress.DisplayName);
            Console.WriteLine("---- " + i.ToString());
            i++;
        }
    }
}

c#中一个优雅的分隔逗号分隔的电子邮件地址列表的方法

试试这个:

public List<string> ExtractEmails(string emails)
{
    List<string> result = new List<string>();
    while (true)
    {
        int position_of_at = emails.IndexOf("@");
        if (position_of_at == -1)
        {
            break;
        }
        int position_of_comma = emails.IndexOf(",", position_of_at);
        if (position_of_comma == -1)
        {
            result.Add(emails);
            break;
        }
        string email = emails.Substring(0, position_of_comma);
        result.Add(email);
        emails = emails.Substring(position_of_comma + 1);
    }
    return result;
}

假设所有的电子邮件都将包含@字符。

它只考虑出现在@字符之后的逗号作为分隔逗号,其他逗号被认为是电子邮件的一部分。

这里有一个漂亮而优雅的简短方法,它将使用正则表达式完成您的要求:

private IEnumerable<string> GetEmails(string input)
{
    if (String.IsNullOrWhiteSpace(input)) yield break;
    MatchCollection matches = Regex.Matches(input, @"[^'s<]+@[^'s,>]+");
    foreach (Match match in matches) yield return match.Value;
}

你可以这样调用它:

string str = "Last, First <name@domain.com>, name@domain.com, First Last <name@domain.com>, '"First Last'" <name@domain.com>, '"Last, First'" <name@domain.com>";
IEnumerable<string> emails = GetEmails(str);

请注意,这个正则表达式不验证电子邮件地址,例如,电子邮件1@h将被认为是有效的,你将得到它作为一个匹配。

创建这样一个正则表达式验证器将是一项困难的工作,可能不是最好的选择。

对于检索目的,我认为它是理想的工具。

不是很优雅,但是试试这个:

        private static IEnumerable<string> GetEntries(string str)
        {
            List<string> entries = new List<string>();
            StringBuilder entry = new StringBuilder();
            while (str.Length > 0)
            {
                char ch = str[0];
                //If the first character on the string is a comma, and the entry already contains na '@'
                //Add this entry to the entries list and clear the temporary entry item.
                if (ch == ',' && entry.ToString().Contains("@"))
                {
                    entries.Add(entry.ToString());
                    entry.Clear();
                }
                //Just add the chacacter to the temporary entry item, otherwise.
                else
                {
                    entry.Append(ch);
                }
                str = str.Remove(0, 1);
            }
            //Add the last entry, which is still in the buffer because it doesn't end with a ',' character.
            entries.Add(entry.ToString());
            return entries;
        }

它将用逗号分隔条目,但仅限于那些在','字符之前包含'@'字符的条目。

你可以这样调用它:

string str = "Last, First <name@domain.com>, name@domain.com, First Last <name@domain.com>, '"First Last'" <name@domain.com>, '"Last, First'" <name@domain.com>";
var entries = GetEntries(str);

最短的方法是:

        string str = "Last, First <name1@domain.com>, name2@domain.com, First Last <name3@domain.com>, '"First Last'" <name4@domain.com>, '"Last, First'" <name5@domain.com>";
        string[] separators = new string[] { "com>,","com,","com>","com"};
    var outputEmail = str.Split(separators,StringSplitOptions.RemoveEmptyEntries).Where(s=>s.Contains("@")).Select(s=>{return s.Contains('<') ? (s+"com>").Trim() : (s+"com").Trim();});
        foreach (var email in outputEmail)
        {
            MessageBox.Show(email);
        }

您可以将Regex.Split@"(?<=@'S*)'s+一起使用-它在包含@的单词前面的空格上分割:

string str = "Last, First <name@domain.com>, name@domain.com, First Last <name@domain.com>,  '"First Last'" <name@domain.com>, '"Last, First'" <name@domain.com>";
string[] arr = Regex.Split(str, @"(?<=@'S*)'s+");
foreach (var s in arr)
    Console.WriteLine(s);
输出:

Last, First <name@domain.com>,
name@domain.com,
First Last <name@domain.com>,
"First Last" <name@domain.com>,
"Last, First" <name@domain.com>

这个版本处理了更多的边缘情况,并且分配了更少的内存:

public static List<string> ExtractEmailAddresses(string text)
{
    var items = new List<string>();
    if (String.IsNullOrEmpty(text))
    {
        return items;
    }
    int start = 0;
    bool foundAt = false;
    int comment = 0;
    for (int i = start; i < text.Length; i++)
    {
        switch (text[i])
        {
            case '@':
                if (comment == 0) { foundAt = true; }
                break;
            case '(':
                comment++;
                break;
            case ')':
                comment--;
                break;
            case ',':
                HandleLastBlock(i);
                break;
        }
    }
    HandleLastBlock(text.Length);
    return items;
    void HandleLastBlock(int end)
    {
        if (comment == 0 && foundAt && start < end - 1)
        {
            var email = new System.Net.Mail.MailAddress(text.Substring(start, end - start));
            items.Add(email.Address);
            start = end + 1;
            foundAt = false;
        }
    }
}

Try

UserEmails?.Split(';',',',' ',''n',''t').Where(x => !string.IsNullOrWhiteSpace(x)).ToList();