我正在尝试编写一个匹配嵌套括号的正则表达式,例如:
"(((text(text))))(text()()text)(casual(characters(#$%^^&&#^%#@!&**&#^*!@#^**_)))"
应该匹配这样的字符串,因为所有嵌套的括号都是关闭的,而是:
"(((text)))(text)(casualChars*#(!&#*(!))"
不应该或者更好的是,应该至少匹配第一个"(((text)))(text)"部分.
实际上,我的正则表达式是:
 $regex = '/( (  (\() ([^[]*?)  (?R)?  (\))  ){0,}) /x';
但它并没有像我期待的那样正常工作.如何解决?我哪里错了?谢谢!
Cas*_*yte 12
这种模式有效:
$pattern = '~ \( (?: [^()]+ | (?R) )*+ \) ~x';
括号内的内容简单描述:
"所有不是括号或递归(=其他括号)"x 0或更多次
如果要捕获括号内的所有子字符串,必须将此模式放在前瞻中以获取所有重叠结果:
$pattern = '~(?= ( \( (?: [^()]+ | (?1) )*+ \) ) )~x';
preg_match_all($pattern, $subject, $matches);
print_r($matches[1]);
请注意,我添加了一个捕获组,我已将其替换(?R)为(?1):
(?R) -> refers to the whole pattern (You can write (?0) too)
(?1) -> refers to the first capturing group
这个先行技巧是什么?
前瞻(或后瞻)内的子模式与任何东西都不匹配,它只是一个断言(一个测试).因此,它允许多次检查相同的子字符串.
如果显示整个模式results(print_r($matches[0]);),您将看到所有结果都是空字符串.获取前瞻中子模式找到的子串的唯一方法是将子模式包含在捕获组中.
注意:递归子模式可以像这样改进:
\( [^()]*+ (?: (?R) [^()]* )*+ \)
当我找到这个答案时,我无法弄清楚如何修改模式以使用我自己的分隔符 where{和}。所以我的方法是让它更通用。
$delimiter_wrap  = '~';
$delimiter_left  = '{';/* put YOUR left delimiter here.  */
$delimiter_right = '}';/* put YOUR right delimiter here. */
$delimiter_left  = preg_quote( $delimiter_left,  $delimiter_wrap );
$delimiter_right = preg_quote( $delimiter_right, $delimiter_wrap );
$pattern         = $delimiter_wrap . $delimiter_left
                 . '((?:[^' . $delimiter_left . $delimiter_right . ']++|(?R))*)'
                 . $delimiter_right . $delimiter_wrap;
/* Now you can use the generated pattern. */
preg_match_all( $pattern, $subject, $matches );