正则表达式递归代码块内容
Regex recursive code block content
我需要使用 RegEx 获取 2 个指令(embed
和 endembed
)之间的内容。我当前的模式正确地做到了这一点 /(?<!\w)(\s*)@embed(\s*\(.*\))([\w\W]*?)@endembed/g
.
但是,当指令嵌套时,它不能正确匹配块。 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。折腾了好几个小时,还是没搞定。
我做错了什么,正确的模式是什么?
我从一个例子中想出了这个递归正则表达式(来自这个 Whosebug answer):
(?=(@embed(?:(?>(?:(?!@embed|@endembed).)+)*|(?1))*@endembed))
在 regex101
上试用
要捕获外部 @embed
和嵌套的,请使用 recursive regex:
$pattern = '/@embed\s*\([^)]*\)((?>(?!@(?:end)?embed).|(?0))*)@endembed/s';
在 (?0)
处粘贴了图案。参见 test at regex101。匹配出时用捕获的 </code> 替换:</p>
<pre><code>$res = array();
while (preg_match_all($pattern, $str, $out)) {
$str = preg_replace($pattern, "", $str);
$res = array_merge($res, $out[1]);
}
这将为您提供最外层和嵌套的直到最内层。 Test at eval.in
没有任何捕获的基本递归模式很简单as this:
/@embed\b(?>(?!@(?:end)?embed\b).|(?0))*@endembed/s
- 匹配文字
@embed
后跟 \b
word boundary
(?>
使用非捕获 atomic group 进行交替:
- 交替:
(?!@(?:end)?embed).
一个字符that starts not@embed
或@endembed
|(?0)
或者从头开始粘贴模式。 )*
整个事情任意次数。
- 匹配文字
@endembed
我需要使用 RegEx 获取 2 个指令(embed
和 endembed
)之间的内容。我当前的模式正确地做到了这一点 /(?<!\w)(\s*)@embed(\s*\(.*\))([\w\W]*?)@endembed/g
.
但是,当指令嵌套时,它不能正确匹配块。 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。折腾了好几个小时,还是没搞定。
我做错了什么,正确的模式是什么?
我从一个例子中想出了这个递归正则表达式(来自这个 Whosebug answer):
(?=(@embed(?:(?>(?:(?!@embed|@endembed).)+)*|(?1))*@endembed))
在 regex101
上试用要捕获外部 @embed
和嵌套的,请使用 recursive regex:
$pattern = '/@embed\s*\([^)]*\)((?>(?!@(?:end)?embed).|(?0))*)@endembed/s';
在 (?0)
处粘贴了图案。参见 test at regex101。匹配出时用捕获的 </code> 替换:</p>
<pre><code>$res = array();
while (preg_match_all($pattern, $str, $out)) {
$str = preg_replace($pattern, "", $str);
$res = array_merge($res, $out[1]);
}
这将为您提供最外层和嵌套的直到最内层。 Test at eval.in
没有任何捕获的基本递归模式很简单as this:
/@embed\b(?>(?!@(?:end)?embed\b).|(?0))*@endembed/s
- 匹配文字
@embed
后跟\b
word boundary (?>
使用非捕获 atomic group 进行交替:- 交替:
(?!@(?:end)?embed).
一个字符that starts not@embed
或@endembed
|(?0)
或者从头开始粘贴模式。)*
整个事情任意次数。 - 匹配文字
@endembed