正在查找正则表达式以查找大字符串中引用的换行符(对于C#)
我有一个很大的字符串(我们称之为CSV文件,虽然它实际上不是一个,但现在更容易),我必须用C代码解析它。正在查找正则表达式以查找大字符串中引用的换行符(对于C#),c#,regex,C#,Regex,我有一个很大的字符串(我们称之为CSV文件,虽然它实际上不是一个,但现在更容易),我必须用C代码解析它。 解析过程的第一步只需使用StreamReader对象并调用ReadLine直到文件完成,即可将文件拆分为单独的行。但是,任何给定的行都可能包含一个带引号(单引号)的文字和嵌入的换行符。我需要找到这些换行符,并将它们临时转换为其他类型的标记或转义序列,直到我将文件拆分为一个行数组。然后我可以将它们更改回原来的位置 输入数据示例: 1,2,10,99,'Some text without a n
解析过程的第一步只需使用
StreamReader
对象并调用ReadLine
直到文件完成,即可将文件拆分为单独的行。但是,任何给定的行都可能包含一个带引号(单引号)的文字和嵌入的换行符。我需要找到这些换行符,并将它们临时转换为其他类型的标记或转义序列,直到我将文件拆分为一个行数组。然后我可以将它们更改回原来的位置
输入数据示例:
1,2,10,99,'Some text without a newline', true, false, 90
2,1,11,98,'This text has an embedded newline
and continues here', true, true, 90
我可以通过使用
string.IndexOf
来编写完成此任务所需的所有C#代码,以找到引用的部分并在其中查找换行符,但我认为正则表达式可能是更好的选择(即编辑:对不起,我误解了你的帖子。如果您正在寻找正则表达式,那么这里有一个:
content = Regex.Replace(content, "'([^']*)\n([^']*)'", "'\1TOKEN\2'");
可能会有边缘情况和这两个问题,但我认为大多数情况下应该是可以的。正则表达式所做的是,它首先找到任何一对在它之间有\n的单引号,并用保留其间任何文本的标记\n替换它
但是,我还是会像下面@bryans解释的那样使用状态机。如果将整个文件放入一个变量中,然后根据不带引号的换行符将其拆分,会怎么样?因为这不是一个真正的CSV文件,它有任何模式吗 从您的示例来看,您似乎有: int,int,int,int,string,bool,bool,int 这构成了你的记录/对象 假设您的数据格式正确(我对您的来源了解不够,无法知道此假设的有效性);你可以:
如果可能的话,我会避免使用正则表达式。使用C#2.0迭代器可以简化执行此类任务的状态机。希望这是我将要编写的最后一个CSV解析器。整个文件被视为一组可枚举字符串,即行/列。IEnumerable很好,因为它可以由LINQ操作符处理
public class CsvParser
{
public char FieldDelimiter { get; set; }
public CsvParser()
: this(',')
{
}
public CsvParser(char fieldDelimiter)
{
FieldDelimiter = fieldDelimiter;
}
public IEnumerable<IEnumerable<string>> Parse(string text)
{
return Parse(new StringReader(text));
}
public IEnumerable<IEnumerable<string>> Parse(TextReader reader)
{
while (reader.Peek() != -1)
yield return parseLine(reader);
}
IEnumerable<string> parseLine(TextReader reader)
{
bool insideQuotes = false;
StringBuilder item = new StringBuilder();
while (reader.Peek() != -1)
{
char ch = (char)reader.Read();
char? nextCh = reader.Peek() > -1 ? (char)reader.Peek() : (char?)null;
if (!insideQuotes && ch == FieldDelimiter)
{
yield return item.ToString();
item.Length = 0;
}
else if (!insideQuotes && ch == '\r' && nextCh == '\n') //CRLF
{
reader.Read(); // skip LF
break;
}
else if (!insideQuotes && ch == '\n') //LF for *nix-style line endings
break;
else if (ch == '"' && nextCh == '"') // escaped quotes ""
{
item.Append('"');
reader.Read(); // skip next "
}
else if (ch == '"')
insideQuotes = !insideQuotes;
else
item.Append(ch);
}
// last one
yield return item.ToString();
}
}
公共类CsvParser
{
公共字符字段分隔符{get;set;}
公共CsvParser()
:此(“,”)
{
}
公共CsvParser(字符字段分隔符)
{
FieldDelimiter=字段分隔符;
}
公共IEnumerable解析(字符串文本)
{
返回解析(新的StringReader(文本));
}
公共IEnumerable解析(TextReader)
{
while(reader.Peek()!=-1)
输出返回行(读卡器);
}
IEnumerable语法行(文本阅读器)
{
bool-insideQuotes=假;
StringBuilder项=新的StringBuilder();
while(reader.Peek()!=-1)
{
char ch=(char)reader.Read();
char?nextCh=reader.Peek()>-1?(char)reader.Peek():(char?)null;
if(!insideQuotes&&ch==字段分隔符)
{
收益返回项.ToString();
项目长度=0;
}
如果(!insideQuotes&&ch='\r'&&nextCh='\n')//CRLF
{
reader.Read();//跳过LF
打破
}
else如果(!insidequeotes&&ch='\n')//LF用于*nix样式的行尾
打破
else if(ch='''&&nextCh=''')//转义引号
{
项目.附加(“”);
reader.Read();//跳过下一步”
}
else如果(ch==“”)
insideQuotes=!insideQuotes;
其他的
项目.附加(ch);
}
//最后一个
收益返回项.ToString();
}
}
请注意,文件是逐字符读取的,代码决定何时将换行符视为行分隔符或带引号字符串的一部分