Согласитесь, что Regex не является подходящим инструментом для этой работы.
Я занимался очисткой этого кода, когда Томас опубликовал эту ссылку на симпатичную маленькую жемчужину в фреймворке. Я использовал этот метод для разбора текста с разделителями, который может содержать строки в кавычках и escape-символы. Возможно, он не самый оптимизированный в мире, но, на мой взгляд, он довольно читабелен, и он выполняет свою работу.
/// <summary>
/// Breaks a string into tokens using a delimeter and specified text qualifier and escape sequence.
/// </summary>
/// <param name="line">The string to tokenize.</param>
/// <param name="delimeter">The delimeter between tokens, such as a comma.</param>
/// <param name="textQualifier">The text qualifier which enables the delimeter to be embedded in a single token.</param>
/// <param name="escapeSequence">The escape sequence which enables the text qualifier to be embedded in a token.</param>
/// <returns>A collection of string tokens.</returns>
public static IEnumerable<string> Tokenize( string line, char delimeter, char textQualifier = '\"', char escapeSequence = '\\' )
{
var inString = false;
var escapeNext = false;
var token = new StringBuilder();
for (int i = 0 ; i < line.Length ; i++) {
// If the last character was an escape sequence, then it doesn't matter what
// this character is (field terminator, text qualifier, etc) because it needs
// to appear as a part of the field value.
if (escapeNext) {
escapeNext = false;
token.Append(line[i]);
continue;
}
if (line[i] == escapeSequence) {
escapeNext = true;
continue;
}
if (line[i] == textQualifier) {
inString = !inString;
continue;
}
// hit the end of the current token?
if (line[i] == delimeter && !inString) {
yield return token.ToString();
// clear the string builder (instead of allocating a new one)
token.Remove(0, token.Length);
continue;
}
token.Append(line[i]);
}
yield return token.ToString( );
}