2015-08-02 3 views
3

Мне нужно получить контент между двумя директивами (embed и endembed) с использованием RegEx. Мой текущий шаблон делает это правильно /(?<!\w)(\s*)@embed(\s*\(.*\))([\w\W]*?)@endembed/g.Содержимое рекурсивного кода кода Regex

Однако, когда директивы вложены, они не соответствуют блокам правильно. https://regex101.com/r/nL8gV5/2,

@extends('layouts/default') 

@section('content') 
    <div class="row"> 
     <div class="col-md-6"> 
      @embed('components/box') 
       @section('title', 'Box title') 
       @section('content') 
        <h4>Haai</h4> 
        Box content 
       @stop 
      @endembed 
     </div> 
     <div class="col-md-6"> 
      @embed('components/box') 
       @section('title', 'Box2 title') 
       @section('content') 

        @embed('components/timeline') 
         @section('items') 
         @stop 
        @endembed 

       @stop 
      @endembed 
     </div> 
    </div> 
@stop 

Желаемый результат:

1:  
@section('title', 'Box title') 
@section('content') 
    <h4>Haai</h4> 
    Box content 
@stop 

2: 
@section('title', 'Box2 title') 
@section('content') 
    @embed('components/timeline') 
     @section('items') 
     @stop 
    @endembed 
@stop 

3: 
@section('items') 
@stop 

Я пробовал различные модели, но я не могу показаться, чтобы получить это право. Насколько я понимаю, я должен использовать рекурсивный токен (R?) в сочетании с обратной ссылкой? что-то более подобное https://regex101.com/r/nL8gV5/3. Проведя несколько часов возиться, я до сих пор не работал.

Что я делаю неправильно и что такое правильный шаблон?

+0

звуков, как это можно было бы сделать гораздо проще, без регулярных выражений, или скажет, с помощью регулярных выражений только найти начальные и конечные тег , любая причина, по которой вы хотите сделать все это в регулярном выражении? – hoijui

+0

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

ответ

1

Чтобы захватить внешние @embed и вложенные из них, используйте recursive regex:

$pattern = '/@embed\s*\([^)]*\)((?>([email protected](?:end)?embed).|(?0))*)@endembed/s'; 

В (?0) шаблон наклеен. См. test at regex101. Заменить захваченной $1, подбирая из:

$res = array(); 

while (preg_match_all($pattern, $str, $out)) { 
    $str = preg_replace($pattern, "$1", $str); 
    $res = array_merge($res, $out[1]); 
} 

Это даст вам внешние и вложенные из них до сокровенной. Test at eval.in


Основной рекурсивный шаблон без захвата как простой as this:

/@embed\b(?>([email protected](?:end)?embed\b).|(?0))*@endembed/s 
  • Match буквального @embed следует \bword boundary
  • (?> Использования не захватывая atomic group для чередования:
  • Alt ernate между: ([email protected](?:end)?embed). A символ that starts not@embed или @endembed |(?0) ИЛИ вставьте шаблон с начала. )* Все это любое количество раз.
  • Match буквального @endembed

Использование s (PCRE_DOTALL)flag для изготовления dot также соответствует новой строке

+0

Очень четкое объяснение, очень ценится! –

+0

@RobinRadic добро пожаловать! рад, что это помогло:] –

1

Я придумал это рекурсивный регулярное выражение из примера я имел (от этого StackOverflow answer):

(?=(@embed(?:(?>(?:([email protected]|@endembed).)+)*|(?1))*@endembed)) 

ПРИМЕРЬТЕ regex101

+0

Работает по желанию, спасибо. –

Смежные вопросы