PHP regular expression to replace nested () with []

前端 未结 5 1223
感动是毒
感动是毒 2021-01-21 23:25

I am trying to match a string, see example, such that a nested parantheses () is replaced by [] so to not break a parser somewhere else. In this case, I would like to replace t

相关标签:
5条回答
  • 2021-01-21 23:57

    You can't do this reliably with regular expressions. If you choose to go with this method anyway, the answer depends on what assumptions you're willing to make about the input. If, for example, you're willing to assume the innermost parentheses can be replaced, the answer is easy:

    preg_replace('!\(([^()]*)\)!', '{$1}', $input);
    

    If you're specifically looking for nested parentheses, try:

    preg_replace('!\(([^()]*)\(([^()]*)\)([^()]*)\)!', '($1{$2}$3)', $input);
    
    0 讨论(0)
  • 2021-01-21 23:57
    $myStr = "Arman; Dario (10040 Druento (Turin), IT)";
    
    $pattern = "/(.*\(.*)\(([^()]+)\)(.*)/";
    if (preg_match_all($pattern,$myStr,$matches))
        {
            print( $matches[1] . '[' . $matches[2] . ']' . $matches[3] );
        }
    

    You can run it through that until it doesn't match

    while( preg_match_all($pattern,$myStr,$matches)) )
    {
        $mystr = $matches[1] . '[' . $matches[2] . ']' . $matches[3];
    }
    
    0 讨论(0)
  • 2021-01-22 00:08

    You could do this with a for loop and an array acting as a stack. When you find an open bracket, push onto the stack, and when you find a closing bracket pop from the stack. The length of the stack will tell you if you should replace the current bracket.

    $stack = array();
    $str = "Arman; Dario (10040 Druento (Turin), IT)";
    $out = "";
    
    for ($i = 0, $l = strlen($str); $i < $l; ++$i) {
        if ($str[$i] == "(") {
            $stack[] = true;
    
            if (count($stack) % 2) { // alternate between ( and [
                $out .= "(";
            } else {
                $out .= "[";
            }
        } else if ($str[$i] == ")") {
            if (count($stack) % 2) {
                $out .= ")";
            } else {
                $out .= "]";
            }
            array_pop($stack);
        } else {
            $out .= $str[$i];
        }
    }
    

    Here's some sample input and output:

    Arman; Dario (10040 Druento (Turin), IT)
    Arman; Dario (10040 Druento [Turin], IT)
    
    a ( b ( c ( d ) ) e )
    a ( b [ c ( d ) ] e )
    
    a (b  (c) (d) (e) )
    a (b  [c] [d] [e] )
    
    a (b (c (d) (e) (f)))
    a (b [c (d) (e) (f)])
    

    It's not a particularly efficient algorithm (building the string char by char), and it could be a bit smarter about unmatched brackets, but anyway...

    0 讨论(0)
  • 2021-01-22 00:14

    Matching nested parentheses requires a parser for a context-free grammar. You can't do it with a regular expression.

    Lime is a parser written in PHP, but it appears to be abandonware, and its documentation is severely lacking.

    0 讨论(0)
  • 2021-01-22 00:16

    Nested parenthesis cannot be matched with a regular grammar. Therefore, a true regular expression will not be able to match nested parenthesis of an arbitrary depth. See the post Can regular expressions be used to match nested parenthesis? for a more detailed explanation.

    Thankfully, regular expressions in PHP are not actually regular. Perl "regular" expressions support recursive patterns, as described on PHP.net. For this particular problem, have you considered replacing the elements individually with str_replace()? This would only fail if you can encounter unmatched opening and closing parenthesis (e.g. (foo (bar)).

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