The Python Oracle

regex matching char only if a specific char appeared before (conditional regex)

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Hypnotic Puzzle4

--

Chapters
00:00 Question
01:40 Accepted answer (Score 9)
03:10 Answer 2 (Score 3)
03:45 Thank you

--

Full question
https://stackoverflow.com/questions/1530...

Accepted answer links:
[conditional pattern]: http://www.php.net/manual/en/regexp.refe...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #regex #regexlookarounds

#avk47



ACCEPTED ANSWER

Score 9


First you must capture the opening parenthesis and then use a conditional pattern (I know the link is to php.net but I find it useful when referencing regexes, it also includes an example which exactly matches your case) that will only be applied if the first opening parenthesis is matched.

The pattern..

^(\()?0?(5[02-9])(?(1)\))-?(\d{7})$

Will match:

(055)-5555555
(055)5555555 
0555555555

but not:

055)-5555555

Captured groups

  1. The opening parenthesis (empty if not found)
  2. Area code (eg. 55)
  3. The phone number (eg. 5555555)

How it works

The part (\()? matches the opening parenthesis. It's optional.

The part (?(1)\)) checks if the first captured group (in our case the opening parenthesis) has a match, if YES then the string must also match the closing parenthesis.

If no opening parenthesis has been found, the condition is effectively ignored.




ANSWER 2

Score 3


Use the (?(id/name)yes-pattern|no-pattern) syntax to match the closing parenthesis only if the opening parethesis matched:

re.compile(r'^(\()?0?(5[023456789])(?(1)\))-?\d{7}$')

The (?(1)\)) part matches \) if there is a group 1 (the | no pattern is optional).

Demo:

>>> phone.search('(055)-5555555')
<_sre.SRE_Match object at 0x101e18a48>
>>> phone.search('055)-5555555') is None
True