Search code examples
phpregexpreg-match

Regular Expression optional matches without greediness


For educational purposes, I'm trying to match name, phone and email of the following content:

John
+1 288298600
john@site.com

Billy

Mike
+1 768397651
mike@site.com

Patrick
+2 938468172

Jack
jack@site.com

I know how to get all emails and all phones from that, but what I want to do here is different.

I want to get, for each name (John, Billy, Mike, Patrick, Jack) their phone (if any) and their email (if any). So matches would be like

'John',    '+1 288298600',  'john@site.com'
'Billy',   '',             ''
'Mike',    '+1 768397651', 'mike@site.com'
'Patrick', '+2 93868172',  ''
'Jack',    '',             'jack@site.com'

Notice that if there is no corresponding info (phone or email) it matches an empty string. How can I do that?

My attempt: ([A-Za-z0-9]+)(?:.*?(\+.*?)|.*?)(?:.*?(.*?\@site.com)|.*?)

Anyone can guide me in the right direction?


Solution

  • Don't try to do this using multiple matches, it won't lead you anywhere. Instead, match one time per entry, and use capturing groups to extract relevant data.

    Here's an example (with the mx flags):

    ^(?<name>[\p{L}\h]+$)\R
    (?:(?<phone>^\+[\d\h]+$)\R)?
    (?<mail>^.+?@.+?\..+)?
    

    Demo

    The first line matches the name, followed by a newline. The second line is optional - it matches a phone number, followed by a newline. The third line, also optional, matches the mail.

    You may refine the subpatterns if needed, I just picked some which seemed to work with your input data.