C# 在C语言中解析逗号分隔的字符串
我知道如何从coma分隔的字符串中获取子字符串,但这里有一个复杂问题:如果子字符串包含coma怎么办 如果子字符串包含逗号、新行或双引号,则整个子字符串用双引号封装 如果子字符串包含双引号,则双引号将用另一个双引号转义。 最坏的情况是如果我有这样的东西:C# 在C语言中解析逗号分隔的字符串,c#,string,list,parsing,substring,C#,String,List,Parsing,Substring,我知道如何从coma分隔的字符串中获取子字符串,但这里有一个复杂问题:如果子字符串包含coma怎么办 如果子字符串包含逗号、新行或双引号,则整个子字符串用双引号封装 如果子字符串包含双引号,则双引号将用另一个双引号转义。 最坏的情况是如果我有这样的东西: first,"second, second","""third"" third","""fourth"", fourth" 在这种情况下,子字符串是: 第一 第二,第二 三分之一 四,四 第二,第二个是用双引号封装的,我不希望那些双引号出现在
first,"second, second","""third"" third","""fourth"", fourth"
在这种情况下,子字符串是:
第一
第二,第二
三分之一
四,四
第二,第二个是用双引号封装的,我不希望那些双引号出现在列表/数组中
第三个是用双引号封装的,因为它包含双引号,而那些是用传统的双引号转义的。同样,我不想要在列表/数组中封装双引号,也不想要转义双引号的双引号,但我想要作为子字符串一部分的原始双引号。试试这个
字符串输入=第一、第二、第二、第三、第四;
字符串[]输出=输入。拆分新字符串[]{\,\},StringSplitOptions.RemoveEmptyEntries 试试这个
字符串输入=第一、第二、第二、第三、第四;
字符串[]输出=输入。拆分新字符串[]{\,\},StringSplitOptions.RemoveEmptyEntries 使用TextFieldParser的一种方法:
为了
使用TextFieldParser的一种方法:
为了
我建议你为这个问题构造一个小型的状态机。你会有这样的状态: Out-在到达第一个字段之前 InQuoted-你已经离开并到达;现在,您已进入并引用该字段 InQuotedMaybeOut-您被引用并到达;现在,您等待下一个角色判断它是另一个角色还是其他角色;否则,则选择下一个有效状态字符可以是空格、换行符、逗号,这样您就可以决定下一个状态;否则,如果到达,则推送到输出并返回到InQuoted In-after-Out,当除和之外的任何字符到达时,您将自动进入一个不带引号的新字段。 这肯定会正确读取CSV。还可以配置分隔符,以便支持TSV或分号分隔格式
还要记住CSV格式中一个非常重要的情况:引用的字段可能包含新行!另一个需要注意的特殊情况是:空字段,如:,。我建议您为此问题构造一个小型状态机。你会有这样的状态: Out-在到达第一个字段之前 InQuoted-你已经离开并到达;现在,您已进入并引用该字段 InQuotedMaybeOut-您被引用并到达;现在,您等待下一个角色判断它是另一个角色还是其他角色;否则,则选择下一个有效状态字符可以是空格、换行符、逗号,这样您就可以决定下一个状态;否则,如果到达,则推送到输出并返回到InQuoted In-after-Out,当除和之外的任何字符到达时,您将自动进入一个不带引号的新字段。 这肯定会正确读取CSV。还可以配置分隔符,以便支持TSV或分号分隔格式
还要记住CSV格式中一个非常重要的情况:引用的字段可能包含新行!另一个需要注意的特殊情况是:空字段,如:,。这不是最优雅的解决方案,但可能会对您有所帮助。我将循环遍历字符,并对引号进行奇偶计数。例如,如果遇到奇数个引号,则bool为true;如果遇到偶数个引号,则bool为false 此布尔值为true时遇到的任何逗号都不应视为分隔符。如果你知道它是一个分隔符,你可以用这个信息做一些事情。下面我用更易于管理但效率不高的东西替换了分隔符:
bool odd = false;
char replacementDelimiter = "|"; // Or some very unlikely character
for(int i = 0; i < str.len; ++i)
{
if(str[i] == '\"')
odd = !odd;
else if (str[i] == ',')
{
if(!odd)
str[i] = replacementDelimiter;
}
}
string[] commaSeparatedTokens = str.Split(replacementDelimiter);
此时,您应该有一个字符串数组,这些字符串以您想要的逗号分隔。从现在开始,处理引号会更简单
我希望这能对您有所帮助。这不是最优雅的解决方案,但可能会对您有所帮助。我将循环遍历字符,并对引号进行奇偶计数。例如,如果遇到奇数个引号,则bool为true;如果遇到偶数个引号,则bool为false 此布尔值为true时遇到的任何逗号都不应视为分隔符。如果你知道它是一个分隔符,你可以用这个信息做一些事情。下面我用更易于管理但效率不高的东西替换了分隔符:
bool odd = false;
char replacementDelimiter = "|"; // Or some very unlikely character
for(int i = 0; i < str.len; ++i)
{
if(str[i] == '\"')
odd = !odd;
else if (str[i] == ',')
{
if(!odd)
str[i] = replacementDelimiter;
}
}
string[] commaSeparatedTokens = str.Split(replacementDelimiter);
此时,您应该有一个字符串数组,这些字符串以您想要的逗号分隔。从现在开始,处理引号会更简单
我希望这能对您有所帮助。Mini parser
后果
第一
第二
第二
三分之一
四,四
微型解析器
后果
第一
第二,第二
三分之一
四,四
谢谢你的回答,但在我看到它们之前,我写了这个解决方案,虽然不漂亮,但对我来说很有效
string line = "first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\"";
var substringArray = new List<string>();
string substring = null;
var doubleQuotesCount = 0;
for (var i = 0; i < line.Length; i++)
{
if (line[i] == ',' && (doubleQuotesCount % 2) == 0)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
continue;
}
else
{
if (line[i] == '"')
doubleQuotesCount++;
substring += line[i];
//If it is a last character
if (i == line.Length - 1)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
}
}
}
for(var i = 0; i < substringArray.Count; i++)
{
if (substringArray[i] != null)
{
//remove first double quote
if (substringArray[i][0] == '"')
{
substringArray[i] = substringArray[i].Substring(1);
}
//remove last double quote
if (substringArray[i][substringArray[i].Length - 1] == '"')
{
substringArray[i] = substringArray[i].Remove(substringArray[i].Length - 1);
}
//Replace double double quotes with single double quote
substringArray[i] = substringArray[i].Replace("\"\"", "\"");
}
}
谢谢你的回答,但在我看到它们之前,我写了这个解决方案,虽然不漂亮,但对我来说很有效
string line = "first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\"";
var substringArray = new List<string>();
string substring = null;
var doubleQuotesCount = 0;
for (var i = 0; i < line.Length; i++)
{
if (line[i] == ',' && (doubleQuotesCount % 2) == 0)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
continue;
}
else
{
if (line[i] == '"')
doubleQuotesCount++;
substring += line[i];
//If it is a last character
if (i == line.Length - 1)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
}
}
}
for(var i = 0; i < substringArray.Count; i++)
{
if (substringArray[i] != null)
{
//remove first double quote
if (substringArray[i][0] == '"')
{
substringArray[i] = substringArray[i].Substring(1);
}
//remove last double quote
if (substringArray[i][substringArray[i].Length - 1] == '"')
{
substringArray[i] = substringArray[i].Remove(substringArray[i].Length - 1);
}
//Replace double double quotes with single double quote
substringArray[i] = substringArray[i].Replace("\"\"", "\"");
}
}
我觉得分离器似乎更适合于一个;或者是逗号以外的东西。特别是因为您打算在输入中引入逗号。您已经定义了一些与现有CSV标准非常接近的内容。因此,最简单的选择是找到一个已经存在的解析器。如果你必须自己做一个简单的状态机来跟踪你是否处于引用或非引用的值。你可以使用正则表达式吗?我要么像Dave说的那样使用正则表达式,要么使用新行作为分隔符。新行可能更简单,但如果文件可能包含任何内容,正则表达式将为您提供更大的灵活性;或者是逗号以外的东西。特别是因为您打算在输入中引入逗号。您已经定义了一些与现有CSV标准非常接近的内容。因此,最简单的选择是找到一个已经存在的解析器。如果你必须自己做一个简单的状态机来跟踪你是否处于引用或非引用的值。你可以使用正则表达式吗?我要么像Dave说的那样使用正则表达式,要么使用新行作为分隔符。新行可能更简单,但如果文件可能包含任何内容,正则表达式将为您提供更大的灵活性
string line = "first,\"second, second\",\"\"\"third\"\" third\",\"\"\"fourth\"\", fourth\"";
var substringArray = new List<string>();
string substring = null;
var doubleQuotesCount = 0;
for (var i = 0; i < line.Length; i++)
{
if (line[i] == ',' && (doubleQuotesCount % 2) == 0)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
continue;
}
else
{
if (line[i] == '"')
doubleQuotesCount++;
substring += line[i];
//If it is a last character
if (i == line.Length - 1)
{
substringArray.Add(substring);
substring = null;
doubleQuotesCount = 0;
}
}
}
for(var i = 0; i < substringArray.Count; i++)
{
if (substringArray[i] != null)
{
//remove first double quote
if (substringArray[i][0] == '"')
{
substringArray[i] = substringArray[i].Substring(1);
}
//remove last double quote
if (substringArray[i][substringArray[i].Length - 1] == '"')
{
substringArray[i] = substringArray[i].Remove(substringArray[i].Length - 1);
}
//Replace double double quotes with single double quote
substringArray[i] = substringArray[i].Replace("\"\"", "\"");
}
}