Использование групп балансировки регулярных выражений для соответствия тегам вложенности

Я пытаюсь использовать регулярные выражения балансировки групп для соответствия вложенности тегов выглядит следующим образом:

some text ...
 {list}
    nesting loop content
    {list}
        {list}
            {list}
                bala ...
            {/list}
        {/list}
    {/list}

{/list}
end

мой экспрессон:

\{(?<NAME>.+?)\}
[^\{\}]*
    (
        (
            \{(?<NAME2>.+?)\}(?<OPEN>)
            [^\{\}]*?
        )
        (
            \{\/\<NAME2>\}(?<-OPEN>)
            [^\{\}]*?
        )
    )*
    (?(OPEN)(?!))  
\{\/\<NAME>\}

моя проблема:

 only last 2 level pair can match.

1 ответ

Решение

Как правило, чтобы соответствовать вложенным тегам, вам нужно что-то похожее на:

(?>
  \{(?<Open>\w+)\}
  |
  \{/(?<-Open>\<Open>)\}
  |
  (?(Open)[^{}]+)
  )*
(?(Open)(?!))

Рабочий пример: Regex Storm

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

{list}
    nesting loop content
    {world}
        {list}
            {hello}
                bala ...
            {/hello}
        {/list}
    {/world}
{/list}

Заметки:

  • я использую (?(Open)[^{}]+) поэтому мы сопоставляем свободный текст, только если он находится внутри тегов.
  • Я использую ту же группу для верхнего уровня и внутренних уровней.

Твой был довольно близко. В основном вам не хватает одного чередования между средними группами:

(
    \{(?<NAME2>.+?)\}(?<OPEN>)
    [^\{\}]*?
)
| # <---- This
(
    \{\/\<NAME2>\}(?<-OPEN>)
    [^\{\}]*?
)

Рабочий пример

Тем не менее, вы всегда используете последнее значение $NAME2, $NAME2 это стек, но вы никогда не извлекаете из него значения, только нажимаете. Это вызывает ошибку: она также будет соответствовать этой строке (что, вероятно, неправильно):

{list}             # Set $Name = "world"
    nesting loop content
    {world}             # Set $Name2 = "world"
        {world}         # Set $Name2 = "world"
            {hello}     # Set $Name2 = "hello"
                bala ...
            {/hello}    # Match $Name2 ("hello")
        {/hello}        # Match $Name2 ("hello")
    {/hello}            # Match $Name2 ("hello")
{/list}            # Match $Name ("list")

Смотрите также:

Другие вопросы по тегам