捕获分隔符之间的结果。内容可能包含分隔符

Capture results between delimiters. Content may contain a delimiter character

我有以下正则表达式:/@\w+(\(((?:(?!\))\S|\s)*)\))?/m

我期望的值是模板文件,例如:

@for($i = 0; $i < 10; $i++)
    {{ $i }}
@endfor

@if(
    !empty($name)
    && $name == 'Carlos'
)
    Hi Carlos
@endif

@csfr

我无法从 @if 括号中获取完整内容。

预期结果为:

!empty($name)
&& $name == 'Carlos'

但它 returns 因为 empty 函数的右括号:

!empty($name

如何捕获完整的表达式,因为这可能包含对其他函数的调用?

正则表达式调试 link: https://regex101.com/r/58ZbXe/1

试试这个正则表达式:

@(?<begin>[A-Za-z]+)\((?<content>[^@]*)\)[^@]+@(?<end>end)

解释:

  • @:@
  • (?<begin>[A-Za-z]+):第 1 组(开始标记)
    • [A-Za-z]+: 字母字符的任意组合
  • \(:左括号
  • (?<content>[^@]*):第2组(括号内容)
    • [^@]*:@
    • 以外的任意字符
  • \):右括号
  • [^@]+:@
  • 以外的任何字符
  • @:@
  • (?<end>end): 第 3 组(结束标记)
    • @:@
    • end: 结束
    • : 来自第一组的内容

试试看 here.

您可以使用

@\w+(\(((?:[^()]++|(\g<1>))*)\))?

参见regex demo

详情:

  • @ - 一个 @ 字符
  • \w+ - 一个或多个单词字符
  • (\(((?:[^()]++|(\g<1>))*)\))? - 第 1 组(可选):
    • \( - 一个 ( 字符
    • ((?:[^()]++|(\g<1>))*) - 第 2 组:
      • (?:[^()]++|(\g<1>))* - 除了 () 或第 1 组模式
      • 之外的一个或多个字符的零次或多次重复
    • \) - ) 个字符。

这是我能想到的最短的正则表达式:

@\w+\(((\(.*?\)|.)*?)\)

参见 live demo

使用 DOTALL 标志,您的目标在组 1 中。

这通过匹配括号内的内容或括号内的点来实现。


如果您需要从 @if 内容中删除前导换行符:

@\w+\(\n?((\(.*?\)|.)*?)\)

参见 live demo