2014-03-12 191 views
2

我需要一個正則表達式來查找所有起始大括號的末尾大括號。 假設正則表達式查找所有起始大括號的末尾大括號

([(([[(([]))]]))]) -- this one will return true. but 
[](()()[[]])[][[([]) --- this one will return false 

對於這一點,我已經試過如下: -

function check($str) { 
    $output = ""; 
    $pattern = "/(\{[^}]*)([^{]*\})/im"; 
    preg_match($pattern, $str, $match); 
    print_r($match[0]); 
} 

assert(check("[](()()[[]])[][[([])") === FALSE); 

任何幫助,請...

+1

標準定期EXPRES sions不能這樣做,因爲他們不能計數或遞歸。 Perl有一個遞歸擴展,可以做到這一點,但PHP使用PCRE,而不是。 – Barmar

+0

如果我理解的很好,如果括號不平衡,你想獲得假?應該')('返回'true'? –

+0

[正則表達式匹配嵌套大括號]可能的重複(http://stackoverflow.com/questions/2778532/regular-expression-to-match-nested-braces) – Barmar

回答

1

做到這一點(在我看來)最簡單的方法是實現一個堆棧數據結構並傳遞你的字符串。本質的東西,像這樣:

  • 遍歷字符串左如果你發現一個左括號向右
  • ,將其添加到堆棧
  • 否則(你找到一個右括號)確保最頂端項在堆棧中是相同類型的括號(因此請確保如果您發現},堆棧中最頂端的項目是{)。這應該有助於你有這樣的情景:({)}。如果匹配,從堆棧彈出。

如果您在整個字符串中重複上述操作,您應該最終得到一個空的堆棧。這意味着您已經設法將所有左括號與右括號匹配。

0

您可以使用此:

$pattern = '~^(\((?1)*\)|\[(?1)*]|{(?1)*})+$~'; 

(?1)是捕獲組1。因爲我把它捕獲組1本身在該子模式的引用(不匹配的內容),我得到一個遞歸。

我加了錨爲開始^和結尾$的字符串,一定要檢查所有的字符串。

注意:如果你需要檢查不僅包括括號中的字符串,可以相互替換(?1)*有:

(?>[^][}{)(]++|(?1))* 

注2:如果你想有一個空字符串返回true,則必須更換最後量詞+*

工作例如:

function check($str, $display = false) { 
    if (preg_match('~^(\((?1)*\)|\[(?1)*]|{(?1)*})+$~', $str, $match)) { 
     if ($display) echo $match[0]; 
     return true; 
    } 
    elseif (preg_last_error() == PREG_RECURSION_LIMIT_ERROR) { 
     if ($display) echo "The recursion limit has been reached\n"; 
     return -1; 
    } else return false; 
} 

assert(check(')))') === false); 

check('{[[()()]]}', true); 

var_dump(check('{[[()()]]}')); 
相關問題