Удалите все строки (комментарии), начинающиеся с "**", используя Regex (.NET Framework, C#)

Я разрабатываю приложение, которое читает текстовые файлы и работает с ними. Эти текстовые файлы имеют следующую структуру:

** A comment
* A command
Data, data, data
** Some other comment
* Another command
1, 2, 3
4, 5, 6

Я храню весь текстовый файл в памяти, используя string text = File.ReadAllText(file);. Однако я хочу удалить все строки, которые являются комментариями, то есть все строки, начинающиеся с"**".

Этого можно достичь следующим методом:

// this method also removes any white-spaces (this is intended)
string RemoveComments(string textWithComments)
{
    string textWithoutComments = null;

    string[] split = Regex.Split(text.Replace(" ", null), "\r\n|\r|\n").ToArray();
    foreach (string line in split)
        if (line.Length >= 2 && line[0] == '*' && line[1] == '*') continue;
        else textWithoutComments += line + "\r\n";

    return textWithoutComments;
}

Однако на самом деле это невероятно медленно для больших файлов. Я также думаю, что можно заменить весь метод одной строкой кода (возможно, используя Regex). Как я могу этого добиться (я также никогда не использовал регулярное выражение).

PS: я тоже хочу избежать StreamReaderс.

РЕДАКТИРОВАТЬ

Пример файла будет выглядеть так:

** Initial comment
*Command-0
** Some Comment: Header: Text
** Some text: text
*Command-1
**
** Some comment or text
**
*Command-2
*Command-3
      1,            2,            3
      2,            2,            4
      3,            2,            5
** END COMMENT

3 ответа

Решение

Почему не просто:

var text = @"** A comment
* A command
Data, data, data
** Some other comment
* Another command
1, 2, 3
4, 5, 6";

var textWithoutComments = Regex.Replace(text, @"(^|\n)\*\*.*(?=\n)", string.Empty); //this version will leave a \n at the beginning of the string if the text starts with a comment.
var textWithoutComments = Regex.Replace(text, @"(^\*\*.*\r\n)|((\r\n)\*\*.*($|(?=\r\n)))", string.Empty); //this versioh deals with that problem, for a longer regex that treats the first line differently than the other lines (consumes the \n rather than leaving it in the text)

Не знаю про производительность, готовых тестовых данных нет...

PS: Я также склонен полагать, что если вам нужна максимальная производительность, некоторая потоковая передача может быть идеальной, вы всегда можете вернуть строку из метода, если это облегчит дальнейшую обработку. Я думаю, что большинство людей в этом потоке предлагают StreamReader для части итерации / чтения / интерпретации, независимо от типа возвращаемого значения, которое вы решили создать.

Объединение строки будет перераспределять память каждый раз, когда размер строки изменяется.

StringBuilder не будет перераспределять так часто и значительно сократит * время выполнения

string RemoveComments(string textWithComments)
{
    StringBuilder textWithoutComments = new StringBuilder();

    string[] split = text.Replace(" ", null).Split('\r', '\n');
    foreach (string line in split)
        if (line.Length >= 2 && line[0] == '*' && line[1] == '*') continue;
        else textWithoutComments.Append(line + "\r\n");

    return textWithoutComments.ToString();
}

Отредактировано по предложению Алуана

Я знаю, что вы сказали, что не хотите использовать StreamReader, но следующий код может обработать 400000 строк менее чем за полсекунды на моем компьютере. Это просто, понятно и быстро.

static void RemoveCommentsAndWhitespace(string filePath)
{
    if (!File.Exists(filePath))
    {
        Console.WriteLine($"ERR: The file '{filePath}' does not exist.", nameof(filePath));
    }

    string outfile = filePath + ".out";

    using StreamReader sr = new StreamReader(filePath);
    using StreamWriter sw = new StreamWriter(outfile);
    string line;

    while ((line = sr.ReadLine()) != null)
    {
        string tmp = line.Replace(" ", string.Empty);
        if (tmp.StartsWith("**"))
        {
            continue;
        }

        sw.WriteLine(tmp);
    }

    Console.WriteLine($"Wrote to {outfile}.");
}
Другие вопросы по тегам