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++;
}
}
}
试试这个:
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();