Regex for checking if a string has mismatched parentheses?

后端 未结 8 2113
一生所求
一生所求 2020-11-29 05:41

In a PHP script, what regex should I use to check for mismatched parentheses in a string? Things that I want to allow include:

  • This is (ok)
  • This (is)
相关标签:
8条回答
  • 2020-11-29 05:49

    Your examples don't include any nested parentheses… if you aren't concerned with nesting, then this can be done using the following expression:

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

    This will match against all the strings in your "allow" list and fail against the strings in your "prevent" list. However, it will also fail against any string with nested parentheses. e.g. "this (is (not) ok)"

    As others have already pointed out, regular expressions are not the correct tool if you need to handle nesting.

    0 讨论(0)
  • 2020-11-29 05:51

    It is not possible to accomplish this with a regex. Brace matching requires a recursive/counting feature that is not available in a regex. You'll need a parser for this.

    More details available here: http://blogs.msdn.com/jaredpar/archive/2008/10/15/regular-expression-limitations.aspx

    0 讨论(0)
  • 2020-11-29 05:57

    Working php without regex:

    function analyse($input){
        $len = strlen($input);
        $depth = 0;
        for ($i = 0; $i < $len; $i++) {
            $depth += $input[$i] == '(';
            $depth -= $input[$i] == ')';
            if ($depth < 0) break;
        }
        if ($depth != 0) return false;
            else return true;
    }
    $check_nestled = analyse('(5 * 2) + ((2 + 2) - 4)');
    if($check_nestled){
        // do stuff, everything is ok
    }
    
    0 讨论(0)
  • 2020-11-29 06:05

    Agree with the fact that this is impossible with a REGEX. You could do the following, though:

    <?php
    
    $testStrings = array( 'This is (ok)', 'This (is) (ok)', 'This is )bad(', 'This is also (bad', 'This is (bad (too)' );
    
    foreach( $testStrings as $string ) {
        $passed = hasMatchedParentheses( $string ) ? 'passed' : 'did not pass';
        echo "The string $string $passed the check for matching parenthesis.\n";
    }
    
    function hasMatchedParentheses( $string ) {
        $counter = 0;
        $length = strlen( $string );
        for( $i = 0; $i < $length; $i ++ ) {
            $char = $string[ $i ];
            if( $char == '(' ) {
                $counter ++;
            } elseif( $char == ')' ) {
                $counter --;
            }
            if( $counter < 0 ) {
                return false;
            }
        }
        return $counter == 0;
    }
    
    ?>
    
    0 讨论(0)
  • 2020-11-29 06:05

    To extend JaredPar's answer, it's not very difficult to solve without using a regex, just write a function that examines each character in the string and increments/decrements a counter. If you find a "(", increment it, and if you find a ")", decrement it. If the counter ever goes below 0, you can break, the string is invalid. When you've processed the whole string, if the counter isn't 0, there was an unmatched open parenthesis.

    0 讨论(0)
  • 2020-11-29 06:08

    Why it's not possible with a regex

    The other answers are all correct, but I just want to put in a plug for theoretical computer science... this is a case where knowing the theory gives an actual practical advantage.

    A regex corresponds to a deterministic finite automaton (DFA), but paren matching require a context-free grammar, which can be realized as a finite automaton (PDA) but not by a DFA.

    Because of this, without a lot of extra brain-work, we know that the answer is no, and we don't have to worry that there is something we're just overlooking. So, you can be confident in the above answers, and not worry that the authors are just overlooking something when they give that answer.

    Almost all compiler books will talk about this, here's a quick overview:

    http://books.google.com/books?id=4LMtA2wOsPcC&pg=PA94&lpg=PA94&dq=push-down+finite+automata&source=bl&ots=NisYwNO1r0&sig=ajaSHFXwpPOWG8IfbcfKoqzS5Wk&hl=en&ei=m26cSdf6DZGYsAPB-6SsAg&sa=X&oi=book_result&resnum=6&ct=result

    0 讨论(0)
提交回复
热议问题