Regex to remove outer brackets

2020-07-18 09:14发布

问题:

I have been using this /\(\s*([^)]+?)\s*\)/ regex to remove outer brackets with PHP preg_replace function (Read more in my previous question Regex to match any character except trailing spaces).

This works fine when there is only one pair of brackets, but problem is when there is more, for example ( test1 t3() test2) becomes test1 t3( test2) instead test1 t3() test2.

I am aware of regex limitations, but it would be nice if I could just make it not matching anything if there is more then one pair of brackets.

So, example behavior is good enough:

( test1 test2 ) => test1 test2

( test1 t3() test2 ) => (test1 t3() test2)

EDIT:

I would like to keep trimming trailing white spaces inside removed brackets.

回答1:

You can use this recursive regex based code that will work with nested brackets also. Only condition is that brackets should be balanced.

$arr = array('Foo ( test1 test2 )', 'Bar ( test1 t3() test2 )', 'Baz ((("Fdsfds")))');
foreach($arr as $str)
   echo "'$str' => " . 
         preg_replace('/ \( \s* ( ( [^()]*? | (?R) )* ) \s* \) /x', '$1', $str) . "\n";

OUTPUT:

'Foo ( test1 test2 )' => 'Foo test1 test2'
'Bar ( test1 t3() test2 )' => 'Bar test1 t3() test2'
'Baz ((("Fdsfds")))' => 'Baz (("Fdsfds"))'


回答2:

Try this

$result = preg_replace('/\(([^)(]+)\)/', '$1', $subject);

Update

\(([^\)\(]+)\)(?=[^\(]+\()

RegEx explanation

"
\(            # Match the character “(” literally
(             # Match the regular expression below and capture its match into backreference number 1
   [^\)\(]       # Match a single character NOT present in the list below
                    # A ) character
                    # A ( character
      +             # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
\)            # Match the character “)” literally
(?=           # Assert that the regex below can be matched, starting at this position (positive lookahead)
   [^\(]         # Match any character that is NOT a ( character
      +             # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
   \(            # Match the character “(” literally
)
"


回答3:

You may want this (As I guess it is what you want originally):

$result = preg_replace('/\(\s*(.+)\s*\)/', '$1', $subject);

This would get

"(test1 test2)" => "test1 test2"
"(test1 t3() test2)" => "test1 t3() test2"
"( test1 t3(t4) test2)" => "test1 t3(t4) test2"