我同意正则表达式不是“正确”的答案,但这是问题所要求的,我喜欢一个好的正则表达式挑战。
下面的模式是我的标准 CSV 解析正则表达式的修改版本,它删除了空格并假设 CSV 按照您的要求是完美的。您的问题中唯一没有解决的部分是它不会删除转义/双引号。模式后给出了取消转义引号的示例。
当 CSV 文件/流的一个或多个行/记录传递给下面的正则表达式时,它将为每个非空行/记录返回一个匹配项。每个匹配项都将包含一个名为的捕获组,该组Value
包含该行/记录中的捕获值。
这是注释模式(在 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|$)";
关于如何使用正则表达式模式的示例(嗯,可以用这种模式替换的原始模式)可以在我对类似问题的回答中找到,或者在C# pad上,或者在这里。
注意:上面的示例包含取消转义/取消双引号的逻辑,如下所示:
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("\"\"", "\""));
}