Python Regex with all optional groups

Viewed 136

I have the current regex pattern:

(.*?)?(?:<)?([\w\.-]+@[\w\.-]+)(?:>)?(.*)?

I have input strings in the form name <email> with the <> included, but sometimes omitted (the reason why I made them a non capturing group). Occasionally I might have text after the email, like name <email> fshasodi for which I've added an extra group to capture it.

Now the problem with my regex is that if there is no email in the string, then it doesn't match the expression. How do I make the email also optional? I understand that it would make all the groups optional, is there a better way I can be doing this in?

1 Answers

You need to use anchors (^ and $) to make sure you match the whole string (or line) and then you need to use an optional non-capturing group around the pattern that matches an email and the rest of the string.

Note your non-capturing groups are redundant, (?:>)? is the same as >?.

Besides, you do not need to escape a dot inside a character class.

Thus, you can use

^(.*?)(?:<?([\w.-]+@[\w.-]+)>?(.*))?$

See the regex demo.

Details:

  • ^ - start of string
  • (.*?) - Capturing group 1: any zero or more chars other than line break chars, as few as possible
  • (?:<?([\w.-]+@[\w.-]+)>?(.*))? - an optional group matching
    • <? - an optional < char
    • ([\w.-]+@[\w.-]+) - Capturing group 2: one or more word, . or - chars, @ and again one or more word, . or - chars
    • >? - an optional > char
    • (.*) - Capturing group 3: any zero or more chars other than line break chars, as many as possible
  • $ - end of string.
Related