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

StackOverflow https://stackoverflow.com/questions/33063

  •  09-06-2019
  •  | 
  •  

我有一个大字符串(让我们将其称为 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 找到引用的部分并在其中查找换行符,但我认为正则表达式可能是更好的选择(即 现在我有两个问题)

有帮助吗?

解决方案

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

从您的示例来看,您似乎有:int、int、int、int、字符串、布尔、布尔、int

这样就构成了您的记录/对象。

假设您的数据格式良好(我对您的来源了解不够,不知道这个假设有多有效);你可以:

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

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

其他提示

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

}

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

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

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

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

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

但我仍然会像 @bryansh 下面解释的那样使用状态机。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top