Регулярное выражение Java - PullRequest
       0

Регулярное выражение Java

6 голосов
/ 19 августа 2010
{
Main Block
     {
     Nested Block
     }
}
{
Main Block 
     {
     Nested Block
     }
     {
     Nested Block
     }
}

Я хочу получать данные в пределах основных блоков, включая вложенные блоки с помощью Java Regex. Возможно ли это?

Заранее спасибо

Ответы [ 3 ]

4 голосов
/ 19 августа 2010

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

Вот EBNF, чтобы вы начали; это неполно, потому что я не знаю, что может быть внутри вашего блока (кроме нескольких блоков):

blocks        ::= { block }
block         ::= "{", block-content, "}"
block-content ::= blocks | things-other-than-blocks

Для некоторых ресурсов по синтаксическому анализу, посмотрите на этот ответ .

3 голосов
/ 19 августа 2010

ЕСЛИ может быть не более 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 недостаточно мощен для его обработки.

1 голос
/ 19 августа 2010

Если вы знаете заранее максимальный уровень вложенности, который может произойти: Рекурсия Regex без балансирующих групп (Соответствие вложенным конструкциям)

Это должно работать для вашего примера.

Но если предположение Вивина верное и вы имеете дело с сколь угодно глубоким вложением, вы захотите последовать его совету и написать парсер.

Или ... если вы в отчаянии, решение, использующее.NET-реализация regex - Balancing Groups или существуют также решения perl regex решение perl 1 , решение perl 2 , решение perl 3 .Эти решения могут обрабатывать неизвестный уровень вложенности, но, увы, не совместимы с регулярными выражениями Java.:(

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...