ЕСЛИ может быть не более 1 уровня вложенности, и символы фигурных скобок не могут быть экранированы, тогда на самом деле шаблон регулярного выражения для этого достаточно прост.
По сути, в некоторых абстрактных обозначениях мы имеем следующую структуру:
{…(?:{…}…)*…}
Вот визуальная разбивка:
___top___
/ nest \
/ / \ \
{…(?:{…}…)*…}
| \______/| |
| | |
open | close
|
zero or more
Конечно, это не совсем регулярное выражение, потому что:
- В "реальном" регулярном выражении мы должны избегать
{
и }
, так как они являются метасимволами
- В «реальном» регулярном выражении нам нужно заменить
…
фактическим шаблоном для содержимого
[^{}]*+
было бы неплохо. […]
- это класс символов . [^…]
- это отрицательный класс символов. *
- ноль или более повтор . +
после спецификатора повторения является собственническим квантификатором.
Таким образом, метод мета-регулярного выражения используется для программного преобразования этого абстрактного шаблона (который читается) в действительный шаблон регулярного выражения (который может быть некрасивым в такие моменты). Вот пример ( также смотрите на ideone.com ):
import java.util.*;
import java.util.regex.*;
//...
Pattern block = Pattern.compile(
"{…(?:{…}…)*…}"
.replaceAll("[{}]", "\\\\$0")
.replace("…", "[^{}]*+")
);
System.out.println(block.pattern());
// \{[^{}]*+(?:\{[^{}]*+\}[^{}]*+)*[^{}]*+\}
String text
= "{ main1 { sub1a } { sub1b } { sub1c } }\n"
+ "{ main2\n"
+ " { sub2a }\n"
+ " { sub2c }\n"
+ "}"
+ " { last one, promise } ";
Matcher m = block.matcher(text);
while (m.find()) {
System.out.printf(">>> %s <<<%n", m.group());
}
// >>> { main1 { sub1a } { sub1b } { sub1c } } <<<
// >>> { main2
// { sub2a }
// { sub2c }
// } <<<
// >>> { last one, promise } <<<
Как видите, фактический шаблон регулярных выражений выглядит следующим образом:
\{[^{}]*+(?:\{[^{}]*+\}[^{}]*+)*[^{}]*+\}
Который как строковый литерал Java:
"\\{[^{}]*+(?:\\{[^{}]*+\\}[^{}]*+)*[^{}]*+\\}"
Изменения
Если уровень вложенности может быть глубже, тогда можно использовать регулярное выражение , все же . Вы также можете разрешить экранирование {
и }
(т.е. использовать в части содержимого, но не в качестве разделителя блоков).
Окончательный шаблон регулярных выражений будет довольно сложным, но в зависимости от того, насколько вы удобны с мета-регулярным выражением (которое требует, чтобы вы были знакомы с самим регулярным выражением), код может быть достаточно читабельным и управляемым.
Если уровень вложенности может быть сколь угодно глубоким, то некоторые разновидности (например, .NET или Perl) все еще могут его обрабатывать, но Java regex недостаточно мощен для его обработки.