你也可以做到这一点,而无需使用正则表达式。下面的扩展方法将允许你指定一个分隔字符和一个字符来开始和结束转义序列。请注意,它不验证所有转义序列都已关闭。
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
检查传递进来,请注意,这两个将返回一个序列与一个空字符串,如果你在一个空字符串传递字符串。
我的建议是,以确保您的分隔符不显示任何其他地方以外,以纪念边界在电子邮件之间,所以不应该允许带'''的电子邮件作为他们名字的一部分(例如“some; [email protected]”)。否则,找到一个不同的分隔符,如管道'|'? – ray
正规救援?也许你可以适应:http://stackoverflow.com/questions/7430186/regex-split-string-with-on-a-delimetersemi-colon-except-those-that-appear-in – Corak
尝试以下方法:'(^ |;)(。*?)@([\ d \ w] + [ - ] *)+ \。\ w +' – Camo