Skip to content
Advertisement

How to capture all but last token in regex when last token can be optional

I have a string in the following format: aaa!bbb.200 where

  • aaa can be anything (any length)
  • bbb can be anything (any length) except !
  • ! & .200 are optional (can be any 3 digit number)

i want to capture bbb and 200

for example:

  1. aaaaa!bbbb.200 i want to capture bbbb & 200
  2. aaa.400 i want to capture 400
  3. aaa!bb i want to capture bb

i have been able to do this with the following regex (?:.*!(.*).(d{3}$)|.*!(.*)|.*.(d{3}$)) but it uses | which complicates the capturing groups, and also seems too long for what i need

trying to capture all but optional last, ends out consuming all string before checking optional.

Advertisement

Answer

You can use

^.*?(?:!([^!]*?))?(?:.(d{3}))?$

See the regex demo. Details:

  • ^ – start of string
  • .*? – zero or more chars other than line break chars as few as possible
  • (?:!([^!]*?))? – an optional sequence matching one or zero occurrences of a ! char and then any zero or more chars other than ! char as few as possible, captured into Group 1
  • (?:.(d{3}))? – an optional sequence matching one or zero occurrences of a . char and then any thre digits, captured into Group 2
  • $ – end of string.
Advertisement