2

I have this rather messy regular expression modified from RegEx for capturing a repeating pattern https://regex101.com/r/Trdwks/1

(([0-9]{1,2}h)[ ]*([0-9]{1,2}min):\s*|([0-9]{1,2}h)():\s*|()([0-9]{1,2}min):\s*)((?:.(?!(\dh\s\d{1,2}min|\dh|\d{1,2}min)))+)

The idea is it matches this string, grouping the hours, minutes, and description.

1h 30min: Title 
- Description Line 1
3h: SECOND TITLE
- Description Line 1
- Description Line 2
- Description Line 3


1h 14min: Title 
- another Great one 42min: Title - Great Movie
- Description Line 2
- Description Line 3

And produces the following the results:

Match 1:
  "1h 30min: Title 
  - Description Line 1"

      Group 1: "1h"
      Group 2: "30min"
      Group 3: "Title 
               - Description Line 1"

Match 2:
  "3h: SECOND TITLE
 - Description Line 1
 - Description Line 2
 - Description Line 3"

      Group 1: "1h"
      Group 2: ""
      Group 3: "SECOND TITLE
               - Description Line 1
               - Description Line 2
               - Description Line 3"

Match 3:
  "1h 14min: Title 
   - another Great one"

      Group 1: "1h"
      Group 2: "14min"
      Group 3: "Title 
                - another Great one"

Match 4:
  "42min: Title - Great Movie
   - Description Line 2
   - Description Line 3"

      Group 1: ""
      Group 2: "42min"
      Group 3: "Title - Great Movie
                - Description Line 2
                - Description Line 3"

I'm having a lot of trouble getting the grouping consistent as the can be only hours, only minutes, or both. So the regex above might put minutes in group 3 or group 6. Is there a way to fix the grouping in the initial or statement to return consistent grouping in each scenario?

Ryan King
  • 2,798
  • 9
  • 37
  • 62

1 Answers1

3

This solution just needs to support lookahead assertion.

(?s)(?=[^:]*\d[^:]*:)(([0-9]{1,2}h)?[ ]*([0-9]{1,2}min)?:\s*)((?:.(?!(\dh\s\d{1,2}min|\dh|\d{1,2}min)))+)

https://regex101.com/r/gz4r9g/1

Expanded

 (?s)
 (?= [^:]* \d [^:]* : )
 (                             # (1 start)
      ( [0-9]{1,2} h )?             # (2)
      [ ]* 
      ( [0-9]{1,2} min )?           # (3)
      : \s* 
 )                             # (1 end)
 (                             # (4 start)
      (?:
           . 
           (?!
                (                             # (5 start)
                     \d h \s \d{1,2} min
                  |  \d h
                  |  \d{1,2} min 
                )                             # (5 end)
           )
      )+
 )                             # (4 end)

This solution just need to support Branch Reset.

(?s)(?|([0-9]{1,2}h)[ ]*([0-9]{1,2}min)|([0-9]{1,2}h)()|()([0-9]{1,2}min)):\s*((?:.(?!(\dh\s\d{1,2}min|\dh|\d{1,2}min)))+)

https://regex101.com/r/pyACdi/1

Expanded

 (?s)
 (?|
      ( [0-9]{1,2} h )              # (1)
      [ ]* 
      ( [0-9]{1,2} min )            # (2)
   |  ( [0-9]{1,2} h )              # (1)
      ( )                           # (2)
   |  ( )                           # (1)
      ( [0-9]{1,2} min )            # (2)
 )
 : \s* 
 (                             # (3 start)
      (?:
           . 
           (?!
                (                             # (4 start)
                     \d h \s \d{1,2} min
                  |  \d h
                  |  \d{1,2} min 
                )                             # (4 end)
           )
      )+
 )                             # (3 end)