6

我的字符串是:(as(dh(kshd)kj)ad)... ()()

如何用正则表达式计算括号?我想选择从第一个左括号开始并在...

将其应用于上面的示例,这意味着我想得到这个字符串:(as(dh(kshd)kj)ad)

我试图写它,但这不起作用:

var str = "(as(dh(kshd)kj)ad)... ()()";
document.write(str.match(/(.*)/m));
4

6 回答 6

8

正如我在评论中所说,与流行的看法相反(不要相信人们所说的一切),使用正则表达式匹配嵌套括号可能的。

使用它的缺点是您只能在固定级别的嵌套中执行此操作。对于您希望支持的每一个额外级别,您的正则表达式将越来越大。

但不要相信我的话。我来给你展示。正则表达式\([^()]*\) 匹配一个级别。对于最多两个级别,请参见此处的正则表达式。为了匹配您的情况,您需要:

\(([^()]*|\(([^()]*|\([^()]*\))*\))*\)

它将匹配粗体部分:(as(dh(kshd)kj)ad)... ()()

在这里查看演示,看看我所说的固定嵌套级别是什么意思。

等等。要继续添加级别,您只需将最后[^()]*一部分更改为([^()]*|\([^()]*\))*在此处检查三个级别)。正如我所说,它会变得越来越大。

于 2013-09-09T17:11:00.330 回答
4

请参阅蒂姆的回答,了解为什么这不起作用,但这里有一个函数可以代替你做你想做的事情。

function getFirstBracket(str){
  var pos = str.indexOf("("),
      bracket = 0;

  if(pos===-1) return false;

  for(var x=pos; x<str.length; x++){
    var char = str.substr(x, 1);    
    bracket = bracket + (char=="(" ? 1 : (char==")" ? -1 : 0));
    if(bracket==0) return str.substr(pos, (x+1)-pos);
  }
  return false;
}

getFirstBracket("(as(dh(kshd)kj)ad)... ()(");
于 2013-09-09T17:01:53.160 回答
4

有一种可能性,你的方法非常好:如果你有一些命中,Match 会给你一个数组,如果是这样,你可以查找数组长度。

var str = "(as(dh(kshd)kj)ad)... ()()",
    match = str.match(new RegExp('.*?(?:\\(|\\)).*?', 'g')),
    count = match ? match.length : 0;

此正则表达式将获取包含圆括号的所有文本部分。请参阅http://gskinner.com/RegExr/以获得一个不错的在线正则表达式测试器。

现在您可以对所有括号使用计数。 match将提供一个如下所示的数组:

["(", "as(", "dh(", "kshd)", "kj)", "ad)", "... (", ")", "(", ")"]

现在您可以开始对结果进行排序:

var newStr = '', open = 0, close = 0;

for (var n = 0, m = match.length; n < m; n++) {
    if (match[n].indexOf('(') !== -1) {
        open++;
        newStr += match[n];
    } else {
        if (open > close) newStr += match[n];
        close++;
    }
    if (open === close) break;
}

...并且newStr将是 (as(dh(kshd)kj)ad)

这可能不是最好的代码,但它会让你更容易理解你在做什么。

使用这种方法,嵌套级别没有限制。

于 2013-09-09T17:30:48.763 回答
3

这对于 JavaScript 正则表达式是不可能的。通常,正则表达式不能处理任意嵌套,因为它不能再用正则语言描述。

一些现代正则表达式风格确实具有允许递归匹配的扩展(如 PHP、Perl 或 .NET),但 JavaScript 不在其中。

于 2013-09-09T16:55:10.100 回答
2

不,正则表达式表达正则语言。有限自动机(FA)是识别常规语言的机器。顾名思义,FA 在内存中是有限的。由于内存有限,FA 无法记住任意数量的括号——这是执行您想要的操作所必需的功能。

我建议您使用涉及枚举器的算法来解决您的问题。

于 2013-09-09T17:12:06.757 回答
1

试试这个jsfiddle

var str = "(as(dh(kshd)kj)ad)... ()()";
document.write(str.match(/\((.*?)\.\.\./m)[1] );
于 2013-09-09T17:01:12.873 回答