user1058797
user1058797

Reputation: 907

PHP Regex with parentheses

I have the below string:

test 13 (8) end 12 (14:48 IN 1ST)

I need the output to be:

14:48 IN 1ST

or everything inside parentheses towards the end of the string.

I don't need, 8 which is inside first set of parentheses. There can be multiple sets of parentheses in the string. I only need to consider everything inside the last set of parentheses of input string.

Upvotes: 3

Views: 17650

Answers (6)

Yevgeny Simkin
Yevgeny Simkin

Reputation: 28349

The easiest thing would be to split the string on ')' and then just grab everything from the last item in the resulting array up till '('... I know it's not strictly regex but it's close enough.

"test 13 (8) end 12 (14:48 IN 1ST)".split( /)/);

This will produce an array with two elements... "test 13 (8" and " end 12 (14:48 IN 1ST"

Notice that no matter how many (xyz) you have in there you will end up with the last one in the last array item.

Then you just look through that last item for a '(' and if it's there grab everything behind it.

I suspect this will work faster than a straight regex approach, but I haven't tested, so can't guarantee that... regardless it does work. [/edit]

Upvotes: -2

Utku Yıldırım
Utku Yıldırım

Reputation: 2277

Regex Explanation

.*       Go to last
\(       Stars with (
([^)]*) 0 or more character except )
\)       Ends with 

preg_match

$str = "test 13 (8) end 12 () (14:48 IN 1ST) asd";
$regex = "/.*\(([^)]*)\)/";
preg_match($regex,$str,$matches);

$matches
array (
  0 => 'test 13 (8) end 12 () (14:48 IN 1ST)',
  1 => '14:48 IN 1ST',
)

Accept Empty preg_match_all

$str = "test 13 (8) end 12 () (14:48 IN 1ST) asd";
$regex = "/\(([^)]*)\)/";

preg_match_all($regex,$str,$matches);

$matches
array (
  0 => 
  array (
    0 => '(8)',
    1 => '()',
    2 => '(14:48 IN 1ST)',
  ),
  1 => 
  array (
    0 => '8',
    1 => '',
    2 => '14:48 IN 1ST',
  ),
)

Don't Accept Empty preg_match_all

$str = "test 13 (8) end 12 () (14:48 IN 1ST) asd";
$regex = "/\(([^)]+)\)/";

preg_match_all($regex,$str,$matches);

$matches
array (
  0 => 
  array (
    0 => '(8)',
    1 => '(14:48 IN 1ST)',
  ),
  1 => 
  array (
    0 => '8',
    1 => '14:48 IN 1ST',
  ),
)

Upvotes: 10

MetaEd
MetaEd

Reputation: 3871

\(.*\) will match the first and last parens. To prevent that, begin with .* which will greedily consume everything up to the final open paren. Then put a capture group around what you want to output, and you have:

.*\((.*)\)

Upvotes: 0

J V
J V

Reputation: 11936

This regex will do: .+\((.+?)\)$

Escape the parentheses, make the + non-greedy with ?, and make sure it's at the end of the line.

If there may be characters after it, try this instead:

.\).+\((.+?)\)

Which basically makes sure only the second parentheses will match. I would still prefer the first.

Upvotes: -1

nickb
nickb

Reputation: 59699

I wouldn't use a regex for this, it's unnecessary.

Use strrpos and substr to extract the string that you need. It's simple, straightforward, and achieves the desired output.

It works by finding the last '(' in the string, and removing one character from the end of the string.

$str = "test 13 (8) end 12 (14:48 IN 1ST)";
echo substr( $str, strrpos( $str, '(')  + 1, -1);

$str = "(dont want to capture the (8)) test 13 (8) end 12 (14:48 IN 1ST)";
echo substr( $str, strrpos( $str, '(')  + 1, -1);

Demo

Edit: I should also note that my solution will work for all of the following cases:

  1. Empty parenthesis
  2. One set of parenthesis (i.e. the string before the desired grouping does not contain parenthesis)
  3. More than three sets of parenthesis (as long as the desired grouping is located at the end of the string)
  4. Any text following the last parenthesis grouping (per the edits below)

Final edit: Again, I cannot emphasis enough that using a regex for this is unnecessary. Here's an example showing that string manipulation is 3x - 7x faster than using a regex.

As per MetaEd's comments, my example / code can easily be modified to ignore text after the last parenthesis.

$str = "test 13 (8) end 12 (14:48 IN 1ST) fkjdsafjdsa";
$beginning = substr( $str, strrpos( $str, '(')  + 1);
substr( $beginning, 0, strpos( $beginning, ')')) . "\n";

STILL faster than a regex.

Upvotes: 3

DV13
DV13

Reputation: 96

I would go with the following regex:

.*\(([^)]+)\)

Upvotes: 0

Related Questions