我对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)?
我得到的最好的是\([^\(]+$
但是,它并不好,而且与我需要的相反。
任何人都可以帮忙吗?
答案 0 :(得分:1)
看看这个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";