正则表达式仅在特定字符之前出现时匹配字符(条件正则表达式)
我正在开发一个用于以色列手机号码的正则表达式。目前我有:
re.compile(r'^[\(]?0?(5[023456789])\)?(\-)?\d{7}$')
这个表达式可以匹配大部分情况。问题是,我想让第二个括号只在第一个括号出现时才匹配。
比如说,(055)-5555555、(055)5555555 或 0555555555 都能匹配,但像 055)-5555555 这样的就不行。
我知道可以用两个正则表达式来测试这个条件(如果第一个匹配,就测试第二个),但这样似乎不是个聪明的解决办法。
我想我需要类似正则表达式的前瞻匹配,但不太确定怎么用,或者我是否理解这个概念。
编辑:解释一下逻辑
区号:应该以5开头,然后是一个特定列表中的单个数字,前面可以有一个可选的零。这个区号也可能在括号里。
接着是一个可选的连字符,后面跟着7个数字。
澄清:我需要让两个括号都匹配,前提是另一个括号存在,这一点对于第一个括号也是如此,我之前没有提到这一点。
2 个回答
3
使用 (?(id/name)yes-pattern|no-pattern)
这种写法,可以让你只在开括号匹配的情况下,匹配到闭括号。
re.compile(r'^(\()?0?(5[023456789])(?(1)\))-?\d{7}$')
这里的 (?(1)\))
这部分的意思是,如果有第1组(也就是开括号),那么就匹配 \)
这个闭括号(后面的 |
后面没有模式是可选的)。
演示:
>>> phone.search('(055)-5555555')
<_sre.SRE_Match object at 0x101e18a48>
>>> phone.search('055)-5555555') is None
True
9
首先,你需要捕捉到开括号,然后使用一个条件模式(我知道这个链接是指向php.net的,但我觉得它在引用正则表达式时很有用,它还包含了一个正好符合你情况的例子),这个条件模式只有在第一个开括号匹配时才会被应用。
这个模式是..
^(\()?0?(5[02-9])(?(1)\))-?(\d{7})$
它会匹配:
(055)-5555555
(055)5555555
0555555555
但不匹配:
055)-5555555
捕获的组
- 开括号(如果没有找到则为空)
- 区号(例如:55)
- 电话号码(例如:5555555)
它是如何工作的
部分(\()?
用于匹配开括号。这个是可选的。
部分(?(1)\))
检查第一个捕获的组(在我们的例子中是开括号)是否有匹配,如果有,那么这个字符串必须也要匹配闭括号。
如果没有找到开括号,这个条件就会被忽略。