3

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.

4
  • 5
    Note that {} are usually referred to as curly brackets (or braces). [] is brackets or square brackets, and what you have are parentheses. Commented Nov 21, 2011 at 23:52
  • @MichaelMior, parentheses are very often referred to as round brackets, too. Commented Nov 22, 2011 at 1:14
  • @Alan - Is this a regional thing? I've never heard such a term. Commented Nov 22, 2011 at 3:57
  • @MichaelMior: I've always assumed it originated outside the U.S., as I've only noticed it in programming-related forums. It seems more appropriate in this context anyway, since we're not using them as sentence punctuation. They're just brackets that happen to be round. Commented Nov 22, 2011 at 5:56

6 Answers 6

10

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',
  ),
)
Sign up to request clarification or add additional context in comments.

4 Comments

See comment on DV13's solution.
This is close; preg_match_all() returns all paren groups. The OP wants the last one only. Suggest you modify the solution to return the last group.
+1 This answer is a good answer if a regex must be used. Otherwise, use string manipulation.
This answer does provide a working regular expression. All the extra code for cases other than the OP requested seems pretty confusing.
3

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.

4 Comments

OP specifically asked for a regex.
@MetaEd - So? People come to SO to learn new methods to achieve their goals, some of which don't really know what they want. Just because they asked for a regex doesn't mean that's what they should be using. Not to mention that a downvote implies that an answer is not useful, which I think we both can agree that this is not the case.
Fair enough, but in that case I suggest revising your solution to allow for the possibility of text after the last close paren. There is none in the example, but it is not ruled out by the problem statement which boils down to "everything inside the last set of parentheses of input string".
Probably the right approach is to post a comment to the question "will you accept an answer that doesn't use regex".
0

I would go with the following regex:

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

1 Comment

Will work, except when the input has empty parens. Empty parens were not ruled out by the problem statement.
0

\(.*\) 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:

.*\((.*)\)

2 Comments

More precisely, \(.*\) matches everything from the first ( to the last ).
Yes. I have fixed the error in my description of that part of the expression.
-1

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.

5 Comments

Will not work if the input has one set of parens, or three or more sets of parens. The way the problem is stated, these are possibilities.
Right, scratch number 2, but number 1 still works if there is no whitespace or other junk at the end.
Right, but I think you are on the right track with your number 2, because the problem statement does not rule out text after the last set of parentheses.
Even if you assume the string ends with ), this doesn't work. \((.+?)\)$ still starts matching at the first (; the non-greedy quantifier doesn't change that. In fact, if you removed the $ it would match the first set of parens. As it is, you'll get everything from the first ( to the final ).
As edited, the first expression will not work if: there is nothing before the last set of parens, or what's inside the parens is null, or there is something after the parens. The second expression makes similar assumptions, and also assumes there are at least two sets of parens. Some of these may make no difference to the OP, but we don't know. The essence of the problem statement is to capture "everything inside the last set of parentheses". Any solution which makes assumptions might just fail for the OP on corner cases.
-2

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]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.