只有在特定字符出现之前匹配字符的正则表达式(条件正则表达式)

4

开发一个匹配以色列手机号码的正则表达式。目前我有以下内容:

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

它抓住了大多数用例。问题在于只有在出现第一个括号时才匹配第二个括号。
例如:(055)-5555555或(055)5555555或0555555555可匹配,但055)-5555555不能。 我知道我可以使用2个正则表达式来测试条件(如果第一个匹配成功,则测试另一个条件),但这似乎不是一个聪明的解决方案。
我猜我需要像正则表达式环视这样的东西,但不确定如何使用它,或者是否正确理解概念。
编辑:解释逻辑
区号:应以5开头,然后是单个数字(来自特定列表),在前面可能有一个零。还有可能会在括号内。 然后是一个可选的连字符, 和7个数字
澄清:如果存在另一个括号,我需要匹配两个括号,对于第一个括号而不仅仅是第二个括号,错过了这一点。

不需要在字符组中放置开括号。\(?就足够了。 - Martijn Pieters
你能列出逻辑要求,而不是要求我们分析你的正则表达式吗? - kjetilh
h = re.compile(r'^[\(]{0,1}0?(5[023456789])\)?(\-)?\d{7}$') - Grijesh Chauhan
环视查找重复字符,而不是匹配字符。您应该捕获括号并测试是否为0或2。 - QuentinUK
@GrijeshChauhan不起作用,匹配了“055)6666666”,这是不应该匹配的,因为只有在第一个括号存在且另一种情况下才会匹配第二个括号。 - alonisser
显示剩余2条评论
2个回答

9
首先,您必须捕获开括号,然后使用条件模式(虽然链接是php.net的,但是我发现在引用正则表达式时很有用,它还包含一个与您的情况完全匹配的示例),只有在第一个开括号匹配时才会应用该模式。
模式...
^(\()?0?(5[02-9])(?(1)\))-?(\d{7})$

匹配

(055)-5555555
(055)5555555 
0555555555

但是不是

055)-5555555

捕获组

  1. 开放括号(如果未找到则为空)
  2. 区号(例如 55)
  3. 电话号码(例如 5555555)

工作原理

(\()? 部分匹配开放括号,它是可选的。

(?(1)\)) 部分检查第一个捕获组(在我们的例子中为开放括号)是否有匹配,如果,则字符串必须也匹配关闭括号。

如果未找到开放括号,则条件被忽略。


3
使用(?(id/name)yes-pattern|no-pattern)语法仅在匹配开括号时才匹配关闭括号:
re.compile(r'^(\()?0?(5[023456789])(?(1)\))-?\d{7}$')

(?(1)\)) 部分会匹配 \),如果有第一组(| 不是必须的模式)。

示例:

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

无法工作...这个匹配 '055)6666666',而不应该匹配。 - alonisser
1
(?(0)\)|) 替换为 (?(1)\)):第一个捕获组是您需要的内容,而 | 和空模式是可选的。 - cooltea
@alonisser:是的,测试0模式(整个匹配)是一个愚蠢的错误。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接