I want to match the digits before h, m, and s into their respective capture groups. I want to match all 3 groups if possible. If one or two of the other groups are missing then match the last group(s).
As seen in the image below and in this 
But I want 7 matches. Where the first match contains 3 groups, the 2:nd to 4:th match contain 2 groups each and the last 3 matches contain 1 group each.
So I want:
- Match 1:
11h22m33s- Group 1:
11 - Group 2:
22 - Group 3:
33
- Group 1:
- Match 2:
11h22m- Group 1:
11 - Group 2:
22
- Group 1:
- Match 3:
11h33s- Group 1:
11 - Group 2:
33
- Group 1:
- Match 4:
22m33s- Group 1:
22 - Group 2:
33
- Group 1:
- Match 5:
11h- Group 1:
11
- Group 1:
- Match 6:
22m- Group 1:
22
- Group 1:
- Match 7:
33s- Group 1:
33
- Group 1:
Edit
The test strings can be contained within other strings! E.g. 08:00 11h. See https://regex101.com/r/RWA9Oy/1
CodePudding user response:
If you need to make sure the whole string matches the pattern, you can use
^(?!$)(?:(\d )h)?(?:(\d )m)?(?:(\d )s)?$
See the regex demo.
If you need to extract these strings from the longer texts, you can use
\b(?=\w)(?:(\d )h)?(?:(\d )m)?(?:(\d )s)?\b(?!\w)
See this regex demo.
Details:
^- start of string(?!$)- the string can't end at the very start (=cannot be empty)\b(?=\w)- a word boundary where the char immediately on the right is a word char (=is a letter, digit or_)(?:(\d )h)?- an optional non-capturing group matching one or more digits (capturing them into Group 1) and ahletter(?:(\d )m)?- an optional non-capturing group matching one or more digits (capturing them into Group 2) and amletter(?:(\d )s)?- an optional non-capturing group matching one or more digits (capturing them into Group 3) and asletter$- end of string\b(?!\w)- a word boundary where the char immediately on the right is NOT a word char or at the end of string.
Just in case you want allow any amount of whitespace between the components, you may add \s*:
^(?!\s*$)\s*(?:(\d )\s*h\s*)?(?:(\d )\s*m\s*)?(?:(\d )\s*s)?\s*$
Or, for partial matching
\b(?=\w)(?:(\d )\s*h\s*)?(?:(\d )\s*m\s*)?(?:(\d )\s*s)?\b(?!\w)
See this regex demo and another regex demo.
