Я согласен, что регулярное выражение не «правильный» ответ, но это то, что вопрос попросил, и мне нравится хороший регулярок вызов.
Образец, приведенный ниже, является модифицированной версией моего standard CSV parsing regex, который удаляет пробелы и предполагает, что CSV идеально по вашему запросу. Единственная часть вашего вопроса, на который он не обратился, заключается в том, что он не удалит скрытые/удвоенные кавычки. Примеры для отмены кавычек приведены после шаблонов.
Когда одна или несколько строк/записи в CSV-файла/потока передаются в регулярном выражении ниже он будет возвращать матч для каждой непустой строки/записи. Каждое совпадение будет содержать группу захвата с именем Value
, которая содержит зафиксированные значения в этой строке/записи.
Вот комментируемого шаблон (проверить это on Regexstorm.net):
(?<=\r|\n|^)(?!\r|\n|$) // Records start at the beginning of line (line must not be empty)
(?: // Group for each value and a following comma or end of line (EOL) - required for quantifier (+?)
[^\S\r\n]* // Removes leading spaces
(?: // Group for matching one of the value formats before a comma or EOL
"(?<Value>(?:[^"]|"")*)"| // Quoted value -or-
(?<Value>[^,\r\n]+)| // Unquoted/open ended quoted value -or-
(?<Value>) // Empty value before comma (before EOL is excluded by "+?" quantifier later)
)
[^\S\r\n]* // Removes trailing spaces
(?:,|(?=\r|\n|$)) // The value format matched must be followed by a comma or EOL
)+? // Quantifier to match one or more values (non-greedy/as few as possible to prevent infinite empty values)
(?:(?<=,)(?<Value>))? // If the group of values above ended in a comma then add an empty value to the group of matched values
(?:\r\n|\r|\n|$) // Records end at EOL
Вот исходный шаблон без всех комментариев или пробелов.
(?<=\r|\n|^)(?!\r|\n|$)(?:[^\S\r\n]*(?:"(?<Value>(?:[^"]|"")*)"|(?<Value>[^,\r\n]+)|(?<Value>))[^\S\r\n]*(?:,|(?=\r|\n|$)))+?(?:(?<=,)(?<Value>))?(?:\r\n|\r|\n|$)
И вот C# экранированием.
String CSVPattern=
@"(?<=\r|\n|^)(?!\r|\n|$)" +
@"(?:" +
@"[^\S\r\n]*" +
@"(?:" +
@"""(?<Value>(?:[^""]|"""")*)""|" +
@"(?<Value>[^,\r\n]+)|" +
@"(?<Value>)" +
@")" +
@"[^\S\r\n]*" +
@"(?:,|(?=\r|\n|$))" +
@")+?" +
@"(?:(?<=,)(?<Value>))?" +
@"(?:\r\n|\r|\n|$)";
Примеры о том, как использовать шаблон регулярных выражений (ну, оригинальный рисунок, который может быть заменен на этой модели) можно найти на мой ответ на аналогичный вопрос here, или на C# pad here или here.
Примечание: Приведенные выше примеры содержат логику для неэкранированными/undoubling кавычки, как показано ниже:
if (Capture.Length == 0 || Capture.Index == Record.Index || Record.Value[Capture.Index - Record.Index - 1] != '\"')
{
// No need to unescape/undouble quotes if the value is empty, the value starts
// at the beginning of the record, or the character before the value is not a
// quote (not a quoted value)
Console.WriteLine(Capture.Value);
}
else
{
// The character preceding this value is a quote
// so we need to unescape/undouble any embedded quotes
Console.WriteLine(Capture.Value.Replace("\"\"", "\""));
}
Почему регулярное выражение? Вам нужно использовать его только? – gdoron
Если CSV абсолютно корректен, у вас есть разрывы строк в полях с указанными полями. – Joey
Я думаю, что метод «split» более подходит для этого случая. –