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 ah
letter(?:(\d )m)?
- an optional non-capturing group matching one or more digits (capturing them into Group 2) and am
letter(?:(\d )s)?
- an optional non-capturing group matching one or more digits (capturing them into Group 3) and as
letter$
- 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.