嵌套匹配的正则表达式

时间:2014-05-25 20:19:23

标签: regex matlab recursion nested

考虑字符串

cos(t(2))+t(51)

使用正则表达式,我想匹配cos(t(2))t(2)t(51)。这适合的一般模式是类似

variable or function name + opening_parenthesis + contents + closing_parenthesis

其中contents可以是具有相同数量的左括号和右括号的任何表达式。

我使用[a-zA-Z]+\([\W\w]*\)返回cos(t(2)))+t(51),这当然不是理想的结果。

有关如何使用正则表达式实现此目的的任何想法?我特别坚持这个"相同数量的开括号和右括号"。

1 个答案:

答案 0 :(得分:4)

Niels,这是一个有趣且棘手的问题,因为你正在寻找重叠的比赛。即使使用递归,任务也不是微不足道的。

你问过any idea how to achieve this with regex,所以听起来即使matlab中没有这个,你会有兴趣看到一个答案,告诉你如何在正则表达式中做到这一点。

这对我来说很有意义,因为工具通常会更改他们使用的正则表达式库。例如,Notepad ++,曾经有瘫痪的正则表达式,在版本6中切换到PCRE。(碰巧,PCRE可以使用这个解决方案。)

在Perl和PCRE中,您可以使用这个简短的正则表达式:

(?=(\b\w+\((?:\d+|(?1))\)))

这将匹配:

cos(t(2))
t(2)
t(51)

例如,在php中,您可以使用此代码(请参阅online demo底部的结果)。

$regex = "~(?=(\b\w+\((?:\d+|(?1))\)))~";
$string = "cos(t(2))+t(51)";
$count = preg_match_all($regex,$string,$matches);
print_r($matches[1]);

它是如何运作的?

  1. 为了允许重叠匹配,我们使用前瞻。这样,匹配cos(t(2))后,引擎会在cos(t(2))之后,o之前cos
  2. 之前定位。
  3. 实际上,引擎实际上并不匹配cos(t(2)),而只是将其捕获到组1.它匹配的是at this position in the string, looking ahead, we can see x的断言。匹配此断言后,它会尝试从字符串中的下一个位置开始再次匹配它。
  4. 前瞻中的表达式(描述了我们正在寻找的内容)几乎非常简单:在(\b\w+\((?:\d+|(?1))\))中,在\d+之后,交替{ {1}}允许我们用|重复第一个子程序,也就是说,我们当前所在的整个表达式。因此,我们不会递归整个正则表达式(包括一个前瞻),而是一个子表达式。