Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex optional group selection doesn't work

Tags:

regex

I want to extract the numbers from the following text:

Something_Time 10 min (Time in Class T>60�C Something Something )
Something_Time 899 min (Time in Class 35�C<T<=40�C Something Something )
Something_Time 0 min (Time in Class T<=-25�C Something Something )

So what I need is:

|---------------|---------------|---------------|
|    Group 1    |    Group 2    |    Group 3    |
|---------------|---------------|---------------|
|      10       |      60       |               |
|---------------|---------------|---------------|
|      899      |      35       |      40       |
|---------------|---------------|---------------|
|      0        |               |      -25      |
|---------------|---------------|---------------|

Group 2 as lower bound and group 3 as upper bound.

I tried the following regex expression:

^.* (\d{1,6}) min .*(?:[ \>](\-?\d{1,2}))?.*(?:[\=](\-?\d{1,2}))?.*$

This unfortunately does not match groups 2 and 3. It works for the second line as soon as the ? is removed from the end of both groups. Do you have any suggestions?

like image 531
Sieck Avatar asked Jul 11 '26 02:07

Sieck


1 Answers

Try:

^Something_Time (\d{1,6}) min(?:.*?[ >](-?\d{1,2}))?(?:.*?[ =](-?\d{1,2}))?.*$

See Regex Demo

  1. ^ Matches start of string.
  2. Something_Time Matches 'Something_Time '
  3. (\d{1,6}) Group 1: 1 - 6 digits
  4. min Matches ' min'
  5. (?:.*?[ >](-?\d{1,2}))? Optional group that matches 0 or more non-newline characters followed by either a space or '>' followed by a number (optional '-' followed by up to 2 digits). The number is placed in Group 2.
  6. (?:.*?[ =](-?\d{1,2}))? Optional group that matches 0 or more non-newline characters followed by either a space or '=' followed by a number (optional '-' followed by up to 2 digits). The number is placed in Group 3.
  7. .* Matches 0 or more non-newline characters.
  8. $ Matches the end of the string or a newline that precedes the end of the string.

In Python:

import re

tests = [
    'Something_Time 10 min (Time in Class T>60�C Something Something )',
    'Something_Time 899 min (Time in Class 35�C<T<=40�C Something Something )',
    'Something_Time 0 min (Time in Class T<=-25�C Something Something )'
]

for test in tests:
    m = re.match(r'^Something_Time (\d{1,6}) min(?:.*?[ >](-?\d{1,2}))?(?:.*?[ =](-?\d{1,2}))?.*$', test)
    if m:
        print(m.groups())

Prints:

('10', '60', None)
('899', '35', '40')
('0', None, '-25')
like image 63
Booboo Avatar answered Jul 15 '26 00:07

Booboo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!