Регулярное выражение C # для анализа json-подобного верхнего объекта

#c# #regex

#c# #регулярное выражение

Вопрос:

Мне нужно проанализировать текстовый файл, подобный json, чтобы извлечь подобные объекты с помощью C # Regex:

 foo {
    line1
    line2
}

bar {
    line3
    line4
}
 

т.е. объекты, которые начинаются и заканчиваются в начале строки.
Тестовый код C #:

 Regex regex = new Regex("\n[^ \n]  \{[.\n] \n\}");
string s = "nfoo {n    line1n    line2n}";
string v = regex.Match(s).Value;
 

это означает:

новая строка-> все, кроме пробела и новой строки-> «{» -> любая вещь плюс новая строка-> новая строка->}

Ожидаемый результат — просто s. Но результатом является пустая строка. Если я удалю "\n\}" в конце:

 Regex regex = new Regex("\n[^ \n]  \{[.\n] ");
string s = "nfoo {n    line1n    line2n}";
string v = regex.Match(s).Value;
 

затем v="nfoo {n"

это работает, как и ожидалось, поэтому кажется, что проблема возникает "\n\}" .

Комментарии:

1. «Нужно готовое решение» — значит, не та платформа, значит, это не сервис по написанию кода…

2. @ sticky bit вы понимаете, что я имею в виду, ответ — всего одна строка кода вместо программы. Поэтому будет лучше, если больше людей сосредоточится на ответе на вопрос, а не на использовании закона вне контекста.

3. синтаксический анализ и регулярное выражение — это совершенно разные вещи. Используйте / напишите синтаксический анализатор для синтаксического анализа

4. @ sticky bit и сэр Руфо: это именно то, что я подразумеваю под «готовым решением». Нестандартное решение не решит проблему, но может привести к обсуждению, которое отнимет время. Причина здесь в том, что написание синтаксического анализатора, например, на основе ANTLR, может стоить новичку нескольких дней, здесь для решения проблемы требуется только одна строка кода.

5.Возможно, ^S s*{n(?:(?!}).*n)*} демонстрация

Ответ №1:

Для вашего примера данных вы могли бы сопоставить первую строку, заканчивающуюся открывающей фигурной скобкой.

Затем используйте повторяющийся шаблон , чтобы соответствовать всей строке , только если она не начинается с закрытия } . Вы могли бы сделать это , используя негативный взгляд (?!}) .

Затем сопоставьте закрывающую фигурную скобку.

 [rn]S s*{[rn](?:(?!}).*[rn])*}
 

О шаблоне

  • [rn] Сопоставление новой строки
  • S s* Сопоставьте 1 раз символ без пробелов, затем 0 раз символ без пробелов
  • {[rn] Открытие матча { с последующим переводом строки
  • (?:(?!}) Отрицательный прогноз, утверждение, что то, что находится прямо справа, не является }
  • .*[rn] Сопоставьте любой символ, кроме новой строки, 0 раз, затем сопоставьте новую строку
  • } Закрытие соответствия }

Демонстрация регулярных выражений .NET | Демонстрация C #

Например:

         Regex regex = new Regex(@"^S s*{[rn](?:(?!}).*[rn])*}"); 
        string s = @"foo {
    line1
    line2
}

bar {
    line3
    line4
}";

        Console.WriteLine(regex.Match(s).Value);
 

Результат:

 foo {
    line1
    line2
}
 

Комментарии:

1. Можете ли вы предоставить рабочий пример на основе моего приведенного выше кода C #? Я пробую новое регулярное выражение (@»^ S s *{ n(?:(?!}).* n)*}»), но все равно получаем пустую строку.

2. @jw_ Я обновил свой ответ и добавил пример использования [rn] для сопоставления с новой строкой ideone.com/6TKDBo

3. Пожалуйста, попробуйте это в моей приведенной выше строке: string s = » nfoo {n line1 n line2 n}»; Я все еще получаю пустую строку. Это из-за » r»? Мой текстовый файл содержит только » n», а не » r n».

4. Ах, если оно должно начинаться с новой строки, затем измените значение ^ на ` n`, например ideone.com/awTfJF Я обновил ответ.

Ответ №2:

Я нахожу рабочее решение:

 Regex r1 = new Regex("\n[^ \n]  \{[\s\S] ?\n\}");
string s = "nfoo {n    line1n    line2n}";
string v = r1.Match(s).Value;
 

теперь v=»nfoo {n line1n line2 n}»

Я новичок в регулярных выражениях, и после дополнительных исследований в ссылке говорится, что когда вы ставите «.» в «[]», точка больше не будет представлять «что-либо». Вы можете использовать «[s S]» для представления всего, включая новую строку.

Комментарии:

1. В этом случае, если у вас есть несколько элементов, вы можете сделать [sS] ? не жадным, используя a ? , иначе вы бы сопоставили больше, чем хотите, см. Демонстрацию

2. @Четвертая птица, вы правы, действительно, я не тестировал приведенный выше код (на foo bar), я нашел это во время другого случая.