簡體   English   中英

用正則表達式計算括號

[英]Count parentheses with regular expression

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

如何用正則表達式計算括號? 我想選擇從第一個開口括號開始並在...之前結束的字符串

將其應用於上面的示例,這意味着我想得到這個字符串:( (as(dh(kshd)kj)ad)

我試着寫它,但這不起作用:

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

這是JavaScript正則表達式無法實現的。 通常,正則表達式無法處理任意嵌套,因為常規語言無法再對其進行描述。

幾個現代的正則表達式風格確實有擴展,允許遞歸匹配(如PHP,Perl或.NET),但JavaScript不在其中。

請參閱蒂姆的回答,了解為什么這不起作用,但這里有一個功能,它會做你所追求的事情。

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)... ()(");

正如我在評論中說,流行的看法相反(不相信一切人說)匹配嵌套的括號內可能的正則表達式。

使用它的缺點是你只能達到固定的嵌套級別 對於您希望支持的每個額外級別,您的正則表達式將越來越大。

但是不要相信我的話。 讓我演示給你看。 正則表達式\\([^()]*\\) 匹配一個級別 最多兩個級別請參見此處的正則表達式 為了符合您的情況,您需要:

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

它將與粗體部分匹配:( (as(dh(kshd)kj)ad) ... ()()

檢查DEMO HERE ,看看我的意思是固定的嵌套水平。

等等。 要繼續添加級別,您所要做的就是將最后一個[^()]*部分更改為([^()]*|\\([^()]*\\))*在此處檢查三個級別 )。 正如我所說,它會變得越來越大。

有可能,你的方法非常好:如果你有一些命中,匹配將給你一個數組,如果是這樣你可以查找數組長度。

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

此正則表達式將獲取包含圓括號的文本的所有部分。 請參閱http://gskinner.com/RegExr/以獲得一個不錯的在線正則表達式測試程序。

現在,您可以對所有括號使用count。 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)

這可能不是最好的代碼,但它會讓你更容易理解你在做什么。

使用這種方法,嵌套級別沒有限制。

不。正則表達式表達常規語言。 有限自動機(FA)是識別常規語言的機器 顧名思義,FA在記憶中是有限的。 在有限的記憶中,FA無法記住任意數量的括號 - 為了做你想做的事所需要的功能。

我建議你使用一個涉及枚舉器的算法來解決你的問題。

試試這個jsfiddle

var str = "(as(dh(kshd)kj)ad)... ()()";
document.write(str.match(/\((.*?)\.\.\./m)[1] );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM