RegEx:紧接在最后一个打开的括号之前的Word

时间:2013-06-06 02:32:43

标签: regex

我对RegEx有一点了解,但此刻,它远远超出了我的能力。

我需要帮助才能找到最后一个没有匹配括号的开括号之前的文本。

(适用于开发中的开源软件的CallTip。)

以下一些例子:

--------------------------
Text               I need
--------------------------
aaa(                  aaa
aaa(x)                ''
aaa(bbb(              bbb
aaa(y=bbb(            bbb
aaa(y=bbb()           aaa
aaa(y <- bbb()        aaa
aaa(bbb(x)            aaa
aaa(bbb(ccc(          ccc
aaa(bbb(x), ccc(      ccc
aaa(bbb(x), ccc()     aaa
aaa(bbb(x), ccc())    ''
--------------------------

是否可以针对这些情况编写RegEx(PCRE)?

我得到的最好的是\([^\(]+$但是,它并不好,而且与我需要的相反。

任何人都可以帮忙吗?

4 个答案:

答案 0 :(得分:1)

enter image description here

看看这个JavaScript函数

var recreg = function(x) {
var r = /[a-zA-Z]+\([^()]*\)/;
while(x.match(r)) x = x.replace(r,'');
return x
}

在应用这个之后,你会留下所有没有关闭副词的不匹配部分,我们只需要最后一个字母。

var lastpart = function(y) { return y.match(/([a-zA-Z]+)\([^(]*$/); }}

这个想法是像

一样使用它
 lastpart(recreg('aaa(y <- bbb()'))

然后检查结果是否为null,否则采用匹配的组result[1]。大多数正则表达式引擎不支持递归正则表达式匹配所需的?R标志。

请注意,这是一个模拟递归正则表达式的示例JavaScript表示。 阅读http://www.catonmat.net/blog/recursive-regular-expressions/

答案 1 :(得分:1)

这适用于所有示例字符串:

\w+(?=\((?:[^()]*\([^()]*\))*[^()]*$)

最有趣的部分是:

(?:[^()]*\([^()]*\))*

它匹配零个或多个平衡的括号对以及它们之前和之间的非paren字符(如示例字符串中的y=bbb()bbb(x), ccc())。当该部分完成时,最终的[^()]*$确保在字符串结束之前不再有任何parens。

但请注意,此正则表达式基于以下假设,即永远不会有多个嵌套级别。换句话说,它假定这些是有效的:

aaa()
aaa(bbb())
aaa(bbb(), ccc())

......但这不是:

aaa(bbb(ccc()))

样本中的字符串ccc(bbb(aaa(似乎意味着确实允许多级嵌套。如果是这种情况,您将无法单独使用正则表达式解决问题。 (当然,一些正则表达式支持递归模式,但即使使用正则表达式标准,语法也很可怕。我保证在你编写它之后一周你就无法阅读自己的正则表达式。)

答案 2 :(得分:0)

部分解决方案 - 假设您的正则表达式是从可以循环的编程语言中调用的。

1)修剪输入:找到匹配的括号,并删除它们之间的所有内容。继续前进,直到没有匹配。正则表达式将查找([^()]) - 左括号,而不是括号,右括号。它必须是“查找和替换无”循环的一部分。这从内到外修剪。

2)修剪后你没有留下括号,或只有前导/尾随。现在你必须在开括号之前找到一个单词。这需要像\w(这样的正则表达式。但如果有多个未闭合的括号,则无效。最后一个可以通过一个贪婪的匹配(在最后\w周围分组)来完成:^.*\w(“尽可能多的字符,直到括号前的一个单词” - 这将找到最后一个之一。

我说的是“近似”解决方案,因为根据您使用的环境,您如何说“此匹配组”以及是否需要在()变化之前加上反斜杠。我把这个细节留在了我的iPhone上很难检查。

我希望这会激励您或其他人提出完整的解决方案。

答案 3 :(得分:0)

不确定您使用的是哪个正则表达式/平台,并且不知道您的平台是否允许使用子模式。但是,对于上面列出的所有情况:

,执行两步后,PHP代码将
$str = 'aaa(bbb(x), ccc()'; // your original string

// find and replace all balanced square brackets with blank
$repl = preg_replace('/ ( \( (?: [^()]* | (?1) )* \) ) /x', '', $str);

$matched = '';
// find word just before opening square bracket in replaced string
if (preg_match('/\w+(?=[^\w(]*\([^(]*$)/', $repl, $arr))
   $matched = $arr[0];
echo "*** Matched: [$matched]\n";

现场演示:http://ideone.com/evXQYt