考虑字符串
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)
,这当然不是想要的结果。
关于如何使用正则表达式实现此目的有什么想法吗?我特别纠结于“左括号和右括号的数量相同”。
最佳答案
Niels,这是一个有趣且棘手的问题,因为您正在寻找重叠的匹配项。即使使用递归,任务也不是微不足道的。
您询问了如何使用正则表达式实现此目的的任何想法
,所以听起来即使这在 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]);
它是如何工作的?
- 为了允许重叠匹配,我们使用了前瞻。这样,在匹配
cos(t(2))
后,引擎将不会将自身定位在cos(t(2))
之后,而是在o
在cos
- 事实上,引擎实际上并不匹配
cos(t(2))
,而只是将其捕获到组 1。它匹配的是断言在字符串中的这个位置,向前看,我们可以看到 x
。匹配此断言后,它会尝试从字符串中的下一个位置开始再次匹配它。 - 前瞻中的表达式(描述我们要查找的内容)几乎非常简单:在
(\b\w+\((?:\d+|(?1 ))\))
,在\d+
之后,交替|
允许我们使用(?1)
重复第一个子例程>,也就是说,我们当前所处的整个表达式。因此,我们不会递归整个正则表达式(包括前瞻),而是递归其子表达式。
关于嵌套匹配的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23859588/