How to replace everything between {} [] () braces

2019-06-20 01:30发布

问题:

I want to remove everything inside braces. For example, if string is:

[hi] helloz [hello] (hi) {jhihi}

then, I want the output to be only helloz.

I am using the following code, however it seems to me that there should be a better way of doing it, is there?

$name = "[hi] helloz [hello] (hi) {jhihi}";
$new  =  preg_replace("/\([^)]+\)/","",$name); 
$new = preg_replace('/\[.*\]/', '', $new);  
$new = preg_replace('/\{.*\}/', '', $new);  
echo $new;

回答1:

This should work:

$name = "[hi] helloz [hello] (hi) {jhihi}";
echo preg_replace('/[\[{\(].*[\]}\)]/U' , '', $name);

Paste it somewhere like: http://writecodeonline.com/php/ to see it work.



回答2:

[old answer]

If needed, the pattern that can deal with nested parenthesis and square or curly brackets:

$pattern = '~(?:(\()|(\[)|(\{))(?(1)(?>[^()]++|(?R))*\))(?(2)(?>[^][]++|(?R))*\])(?(3)(?>[^{}]++|(?R))*\})~';

$result = preg_replace($pattern, '', $str);

[EDIT]

A pattern that only removes well balanced parts and that takes in account the three kinds of brackets:

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

This pattern works well but the additional type check is a bit overkill when the goal is only to remove bracket parts in a string. However it can be used as a subpattern to check if all kind of brackets are balanced in a string.


A pattern that removes only well balanced parts, but this time, only the outermost type of bracket is taken in account, other types of brackets inside are ignored (same behavior than the old answer but more efficient and without the useless conditional tests):

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


回答3:

I made a function for that. It replaces the text in braces (including them) with the text you want. It also works with nested braces. foo(foo(foo)) with bar as replace will return foobar. It also allows collection of replaced text in a var (In such situation, previous example will show foo(foo) as replaced text) with your own key. It does not use regex and allows not only braces, but everything else (but only if its single character... sorry).

function advanced_replace($searchStart, $searchEnd, $replace, $subject, &$assignValue = array(), $addValue = false, $inReplace = false, $valueKey = "") {
    $strlen = strlen( $subject );
    $open = 0;
    $ob = false;
    $ob_message = "";
    $message = "";
    for( $i = 0; $i <= $strlen; $i++ ) {
        $char = substr( $subject, $i, 1 );

        if ($char == $searchStart) {
            $open++;
            $ob = true;
        }
        if ($ob) {
            $ob_message .= $char;
        } else {
            $message .= $char;
        }
        if ($char == $searchEnd) {
            $open--;
            if ($open == 0) {
                $ob = false;
                $message .= ($replace.($addValue!== false && $inReplace?$addValue:""));
                $assignValue[$valueKey.($addValue!== false?$addValue:"")] = $ob_message;
                $ob_message = "";
                if ($addValue !== false) $addValue++;
            }
        }
    }
    return $message; 
}

Arguments:

  • $searchStart is the starting character of search.
  • $searchEnd is the ending character of search
  • $replace is the replacement text.
  • $subject is the text where all replaces happen

Optional elements:

  • &$assignValue is reference to the array variable you want to store replaced text with. Optional
  • $addValue is starting number in counting replacement. It isn't a reference, but if not equal to false (0 can still be), it will be put after the key in $assignValue. It is before $valueKey, because when $valueKey is left empty, it will count like in a normal array (if its not false, of course - in example - 0), like array(0 => "foo", 1 => "bar"). Increases by 1 every replacement.
  • $inReplace (if true) will also put $addValue after replacement, increasing by 1 every action.
  • $valueKey is the key used for all items in the replaced text array. It is highly recommended to set $addValue not false when using - it will return only last item replaced!

Return value:

It does not change any of arguments, but $assignValue. It returns modified $subject and set $assignValue to array of replaced texts.

Example:

$script = "test: (2+2), test: (3*(1+2))";
$script = advanced_replace("(",")", '?_MATH', $script, $vars, 0, true, '_MATH');

return: test: ?_MATH0, test: ?_MATH1

$vars =

array(
[_MATH0] => (2+2)
[_MATH1] => (3*(1+2))
)

Hope it worked. For me it did. If you misunderstood something or found errors in reference, just comment below. (For errors - edit if you know and tested your solution)