寻找正则表达式以大字符串查找带引号的换行符(适用于C#)
我有一个很大的字符串(我称它为CSV文件,尽管实际上不是一个,但现在会更简单),我必须在Ccode中进行解析。
解析过程的第一步是通过仅使用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
来找到引用的部分并在其中查找换行符来编写执行此操作所需的所有Ccode,但是我认为正则表达式可能是一个更好的选择(即,现在我有两个问题)
解决方案
回答
编辑:对不起,我误解了帖子。如果我们正在寻找正则表达式,那么这里是一个:
content = Regex.Replace(content, "'([^']*)\n([^']*)'", "'TOKEN'");
可能存在一些极端情况,并且存在两个问题,但我认为大多数时候都可以。正则表达式的作用是,它首先找到之间有\ n的任何一对单引号,然后用TOKEN替换该\ n并保留中间的任何文本。
但是仍然,我会像下面的@bryansh那样去使用状态机。
回答
如果我们将整个文件放入一个变量,然后根据不带引号的换行符将其拆分怎么办?
回答
我们也可以考虑使用已建立的CSV解析器(例如使用ODBC),但我不认为引用的换行符有效。
回答
由于这不是真正的CSV文件,因此它具有任何形式的架构吗?
从示例中,我们看起来像:
int,int,int,int,string,bool,bool,int
这样就构成了记录/对象。
假设数据格式正确(我对消息来源了解不足,不足以知道此假设的有效性);你可以:
- 阅读台词。
- 使用状态机来解析数据。
- 如果行结束,并且我们正在解析字符串,请阅读下一行并继续进行解析。
如果可能的话,我会避免使用正则表达式。
回答
使用C2.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(); } }
请注意,逐字符读取文件,其代码确定何时将换行符视为行定界符或者带引号的字符串的一部分。