寻找正则表达式以在大字符串中查找带引号的换行符(对于 C#)

Posted

技术标签:

【中文标题】寻找正则表达式以在大字符串中查找带引号的换行符(对于 C#)【英文标题】:Looking for Regex to find quoted newlines in a big string (for C#) 【发布时间】:2010-09-07 04:17:09 【问题描述】:

我有一个大字符串(我们称它为 CSV 文件,虽然它实际上不是一个,但现在它会更容易),我必须在 C# 代码中进行解析。 解析过程的第一步将文件拆分为单独的行,只需使用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

我可以编写执行此操作所需的所有 C# 代码,方法是使用 string.IndexOf 查找引用的部分并在其中查找换行符,但我认为 Regex 可能是更好的选择(即 now I have two problems)

【问题讨论】:

【参考方案1】:

由于这不是一个真正的 CSV 文件,它是否有任何类型的架构?

从您的示例看来,您有: 整数,整数,整数,整数,字符串,布尔,布尔,整数

以此构成您的记录/对象。

假设您的数据格式正确(我对您的来源了解得不够多,无法知道这个假设的有效性);你可以:

    阅读您的台词。 使用状态机解析您的数据。 如果您的行结束,并且您正在解析一个字符串,请阅读下一行......并继续解析。

如果可能,我会避免使用正则表达式。

【讨论】:

【参考方案2】:

使用 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();
    


请注意,文件是逐字符读取的,代码决定何时将换行符视为行分隔符或引用字符串的一部分。

【讨论】:

【参考方案3】:

如果您将整个文件放入一个变量中,然后根据未引用的换行符进行拆分,该怎么办?

【讨论】:

【参考方案4】:

编辑:抱歉,我误解了您的帖子。如果您正在寻找一个正则表达式,那么这里有一个:

content = Regex.Replace(content, "'([^']*)\n([^']*)'", "'\1TOKEN\2'");

可能存在边缘情况和这两个问题,但我认为大多数时候应该没问题。正则表达式的作用是,它首先找到任何一对在其之间有 \n 的单引号,然后用 TOKEN 替换该 \n 并保留其间的任何文本。

但是,我还是会像下面@bryansh 解释的那样使用状态机。

【讨论】:

以上是关于寻找正则表达式以在大字符串中查找带引号的换行符(对于 C#)的主要内容,如果未能解决你的问题,请参考以下文章

Eclipse 用正则表达式查找/替换整行

使用正则表达式将带引号的字符串与嵌入的非转义引号匹配

正则之基本概念

正则表达式应该只匹配两种类型的带引号的字符串之一

正则表达式考点

修改正则表达式以在带有或不带有 http 前缀的字符串中查找 URL [重复]