큰 문자열에서 인용된 개행 문자를 찾기 위해 Regex를 찾고 있습니다(C#의 경우).

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

  •  09-06-2019
  •  | 
  •  

문제

C# 코드에서 구문 분석해야 하는 큰 문자열(CSV 파일이라고 부르겠습니다. 실제로는 아니지만 지금은 더 쉬울 것임)이 있습니다.
구문 분석 프로세스의 첫 번째 단계는 다음을 사용하여 파일을 개별 줄로 분할합니다. 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가 더 나은 선택이 될 수 있다고 생각합니다(예: 이제 두 가지 문제가 생겼습니다)

도움이 되었습니까?

해결책

이것은 실제 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'");

극단적인 경우와 두 가지 문제가 있을 수 있지만 대부분의 경우에는 괜찮을 것이라고 생각합니다.Regex가 수행하는 작업은 먼저 사이에 이 있는 작은따옴표 쌍을 찾아 그 사이의 텍스트를 유지하는 TOKEN으로 을 바꾸는 것입니다.

하지만 여전히 @bryansh가 아래에 설명한 것과 같은 상태 머신으로 갈 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top